Release 2.0

This commit is contained in:
specialworld83 2026-07-15 10:52:22 +02:00
commit f0f913a209
805 changed files with 203292 additions and 5275 deletions

View file

@ -1,133 +1,365 @@
# Changelog
## Release 1.1
### Added
#### Archive Security
- Added ZIP evasion detection for manipulated archives commonly associated with **“Zombie ZIP” techniques**.
- Added archive structure inspection for suspicious ZIP metadata inconsistencies.
- Added detection for `ZIP_STORED_SIZE_MISMATCH` when an entry is marked as `STORED` but compressed and uncompressed sizes differ.
- Added archive risk classification pipeline with support for:
- `CLEAN`
- `SUSPICIOUS`
- `MALFORMED`
- `EVASIVE`
- Added archive inspection result reporting fields for:
- `stored_size_mismatch`
- `header_mismatch`
- `invalid_offset`
- `overlapping_entries`
- `nested_archive`
- `risk_score`
- `reason_code`
- `detail`
- Added `ArchiveInspector` integration into the realtime anti-ransomware engine.
- Added sandboxed archive analysis through a dedicated `archive_worker`.
- Added **Bubblewrap-based isolation** for archive inspection workers.
- Added realtime archive threat signaling through the existing alert socket pipeline.
- Added GUI alert support for suspicious archive detections raised by archive inspection.
- Added delayed archive re-scan support to improve detection reliability after file write completion.
- Added detection coverage for suspicious ZIP files created through **atomic rename / moved-to workflows**.
# BastionGuard™ — Changelog
---
#### Email Security (Mail Proxy)
- Added `BastionGuard-mailproxy`, a **local SMTP protection proxy** for outgoing email security.
- Added support for local SMTP relay listeners on:
- plain SMTP
- submission
- implicit TLS ports
- Added outgoing mail relay selection based on sender address and sender domain matching.
- Added support for **multiple SMTP relay profiles** with per-profile authentication and TLS settings.
- Added automatic fallback import of **SMTP relay profiles from Thunderbird** when JSON mail configuration is unavailable.
- Added **transparent relay mode** for production continuity when email protection is disabled.
## [1.2] — 2026-03-21
---
#### Email Signature Protection
- Added mandatory outgoing **signature injection** support for protected email flows.
- Added plain text signature injection for outgoing emails.
- Added HTML signature injection with inline branded logo support.
- Added multipart MIME signature injection support for compatible email structures.
- Added safe fallback handling for unsupported or malformed MIME signature injection cases.
# 🇬🇧 English
### ✨ New feature: Secure sandbox for payments and banking
Full implementation of the automatic isolation system for banking and payment
sites. When the user navigates to a domain on the bank or payment list,
BastionGuard intercepts the connection, opens an isolated CEF window on the
exact URL, and restores the normal proxy when the window is closed.
---
#### Mail Delivery Reliability
- Added local delivery **queueing** for failed remote SMTP relay attempts.
#### Proxy MITM and interception (`bastionguard_cef.cpp`, `tls_intercept.hpp`)
- **Full URL preserved** — the path and query string (e.g. `/checkoutnow?token=…`)
are extracted from the HTTP request line after the TLS handshake and passed to
the sandbox, instead of opening just `https://host/`. Fixes the PayPal checkout
link case that was opening only `paypal.com` and ignoring the token.
- **No tab loop** — separated "first interception" (Case 3, opens sandbox) from
"session already active" (Case 2, serves block page only). Added atomic guard
`sandbox_try_open/sandbox_close` for parallel requests arriving before the
first `do_intercept` completes.
- **`block_active_session()`** — new variant of `block_secure_request` used in
Case 2: serves the TLS block page with no callback and no `launch_sandbox`,
eliminating the root cause of the tab loop.
- **`launch_sandbox` is now blocking** — removed the `&` from the shell command.
`std::system` now waits for the child process to terminate, enabling
`session_close` on return.
- **`session_close(root)`** — new function that removes the session from
`g_sessions` immediately when the sandbox is closed. `SESSION_TTL` raised from
30 seconds to 30 minutes (safety net for crashes, not the primary mechanism).
- **`BG_SANDBOX=1`** — environment variable passed to sandbox processes
(`BastionGuard-bankopener`, `BastionGuard-secure`) to prevent `LocalWarningServer`
from starting inside them, eliminating interference with internal redirects
(e.g. the vendor's return URL).
- **`SandboxApiServer`** — new HTTP server on `127.0.0.1:3131` handling
`GET /open-sandbox?url=…`. Used by the JS banner injected into e-commerce pages
to open the sandbox on the correct URL without requiring any browser extension.
---
#### TLS & Mail Proxy Infrastructure
- Added self-signed TLS certificate generation for the local mail proxy.
- Added automatic local TLS support for protected SMTP sessions.
- Added Thunderbird certificate installation support for local mail proxy trust.
- Added Thunderbird SMTP redirection support to route outgoing mail through the local BastionGuard proxy.
- Added Thunderbird SMTP restoration logic to safely restore original remote relay settings.
- Added support for STARTTLS and implicit TLS handling in the local SMTP proxy.
- Added support for authenticated SMTP client sessions (`AUTH PLAIN` and `AUTH LOGIN`) on the local proxy.
- Added support for protected relay delivery with optional mandatory signature enforcement.
#### Credit card form detection on e-commerce sites (`card_form_injector.hpp`)
- **`CardFormTunnel`** — replaces `TunnelSession` for CONNECT connections to known
e-commerce domains. Performs double TLS MITM (browser ↔ proxy ↔ server), buffers
the first HTTP response (max 512 KB), analyses the HTML for card form patterns,
injects the BastionGuard banner if found, then switches to transparent relay.
- **`contains_card_form(html)`** — detects card fields via:
- HTML5 `autocomplete` attributes (`cc-number`, `cc-csc`, `cc-exp`)
- Common name/id values (`card_number`, `cardnumber`, `cc_number`, `pan`)
- Placeholder text combined with CVV fields
- SDK attributes from Stripe, Braintree, Adyen, Klarna
- **`inject_into_response()`** — inserts the JS script before `</head>`, updates
`Content-Length`, removes `Transfer-Encoding: chunked` if present.
- **JS banner** — fixed at the bottom of the page, dark theme consistent with
BastionGuard UI. "Pay securely" button calls `SandboxApiServer`; ✕ button
dismisses the banner without opening the sandbox.
- **Three-level filter** to minimise MITM overhead:
1. `should_inspect_for_card_forms(host)` — MITM only on known e-commerce hosts
(~80 sites: Amazon, eBay, Zalando, etc.); CDN and trackers excluded.
2. `is_checkout_path(path)` — inside the MITM, buffers body only when the path
contains checkout keywords (`/checkout`, `/cart`, `/payment`, `/cassa`, etc.).
Product and catalogue pages use transparent relay with no overhead.
3. `contains_card_form(html)` — injects only if the body actually contains a
card form; order confirmation pages without forms produce no banner.
---
### Changed
- Integrated archive inspection into the realtime filesystem monitoring pipeline.
- Updated the realtime ransomware engine to inspect archive files before or alongside standard file scanning.
- Improved anti-ransomware monitoring coverage for compressed archives appearing in watched directories.
- Improved Bubblewrap sandbox profile to work reliably in production service context.
- Refined sandbox namespace configuration to avoid failures caused by unsupported or restricted user/network namespace setup in systemd service environments.
- Preserved sandbox isolation while removing namespace options that caused runtime failures in production.
- Improved alert flow so suspicious archive detections now trigger end-to-end notification correctly.
- Extended BastionGuard with outgoing mail protection through a dedicated local SMTP proxy component.
- Improved email workflow integration by allowing Thunderbird-based relay import and local SMTP redirection.
- Updated email protection flow to preserve delivery continuity through transparent relay fallback and local queueing.
#### CEF sandbox (`SecureBrowser.cpp`)
- **Vendor return URL** — after payment on PayPal (or any gateway), the final
redirect back to the vendor's site is shown directly inside the sandbox.
`LocalWarningServer` no longer interferes thanks to `BG_SANDBOX=1`.
- **Navigation in trusted session** — once the user has visited a trusted domain
(bank or payment), all subsequent redirects inside the sandbox are allowed
without any block, including automatic redirects to the return URL. Only manual
clicks toward external non-trusted domains show the inline block page.
- **`load_block_page_inline(browser, host)`** — new private function of
`SimpleHandler` that generates a block page as `data:text/html,…` directly
in CEF, with no dependency on `LocalWarningServer`.
- **Conditional `start_local_warning_server()`** — in `SecureBrowser::open()`,
the `LocalWarningServer` is started only if the `BG_SANDBOX` environment variable
is not set, preventing the sandbox process from starting a server that would
interfere with its own navigation.
---
### Fixed
#### Block page (`block_page.hpp`)
#### Archive Detection
- Fixed realtime archive inspection not triggering alerts for suspicious ZIP files.
- Fixed Bubblewrap sandbox launch failures caused by `uid map` errors in service context.
- Fixed Bubblewrap failures caused by loopback/network namespace setup inside the realtime daemon.
- Fixed archive inspection pipeline failures where files were detected by inotify but not successfully analyzed in sandbox.
- Fixed end-to-end realtime detection for Zombie ZIP test samples.
- **Inline BastionGuard logo**`load_logo_base64()` loads
`/usr/share/BastionGuard/data/logo.png` and embeds it as a base64 data URI
directly in the HTML. No network request required; works offline and inside the
block page where the connection is already closed. Static cache: file is read
once per process.
#### Localization
- Fixed language initialization bug in `main` where locale variables could be missing or improperly loaded, causing translations to fail or the default language not to be applied correctly.
- Fixed loading and fallback handling for `LANG`, `LC_ALL`, and `LANGUAGE` environment variables using `lang.conf`.
- Ensured safe locale initialization with fallback chain (`setlocale`) to prevent startup issues on systems without configured locales.
- **Emoji fallback** — if the logo file is missing (non-standard installation or
development environment), `🛡️` is used as before. No regressions.
#### Scan Engine
- Fixed `ScanPage` automatic scanning logic:
- removed synchronous subprocess waiting inside asynchronous callbacks
- ensured ClamAV scan completes before triggering cloud reputation checks
- fixed asynchronous scan flow so MalwareBazaar lookups only run after scan EOF
- prevented premature cloud checks triggered by intermediate ClamAV output lines
- reduced potential race conditions during automatic file scanning
- Fixed excessive concurrent cloud lookups by introducing a limit on active MalwareBazaar checks.
- Reduced risk of uncontrolled detached cloud-check thread growth during automatic scanning.
- Improved automatic scan stability in production environments.
- **Updated `.shield` CSS** — supports both `<img>` (PNG logo) and `<span>`
(emoji fallback): fixed size `72×72px`, `object-fit:contain`, blue
`drop-shadow` for both.
---
### Security
- Hardened compressed archive inspection against ZIP-based evasion techniques.
- Improved defense against archive-based AV/EDR bypass attempts using manipulated ZIP metadata.
- Added sandboxed parsing path to reduce risk from malformed or adversarial archive inputs.
- Extended realtime protection to detect suspicious archive structures before user interaction.
- Added protected outgoing email routing through a local SMTP proxy layer.
- Improved outbound mail control with signature enforcement and controlled relay selection.
- Added TLS support for local SMTP proxy sessions to reduce exposure of local mail submission traffic.
- Added safer relay fallback and queueing behavior for failed protected email delivery attempts.
#### Bug fixes
| Component | Bug | Fix |
|---|---|---|
| `bastionguard_cef.cpp` | Thousands of tabs opened on PayPal interception | Separated Case 2 and Case 3; atomic guard on `launch_sandbox` |
| `bastionguard_cef.cpp` | Sandbox opened on `https://paypal.com/` without token | Extracted path from request line after TLS handshake |
| `bastionguard_cef.cpp` | Session remained active after sandbox was closed | `session_close()` + blocking `launch_sandbox` |
| `SecureBrowser.cpp` | Red "Domain blocked" page shown on vendor return URL | `BG_SANDBOX=1` + free navigation in trusted session |
| `SecureBrowser.cpp` | `LocalWarningServer` started inside the sandbox | Conditioned on absence of `BG_SANDBOX` env var |
| `tls_intercept.hpp` | `do_intercept` ignored path and query string | Added `on_url_ready` callback with full URL |
---
### Notes
- Zombie ZIP detection is now active in the production realtime monitoring path.
- Realtime archive detection has been validated with:
- normal ZIP samples
- manipulated Zombie ZIP samples
- Service resource usage remains low after integration, making the feature suitable for continuous protection on production systems.
#### Compatibility
- No changes to the public API of `SecureBrowser`, `DomainFilter`, `BlockPage`.
- `card_form_injector.hpp` is a new optional header; targets that do not include
it are unaffected.
- `BG_SANDBOX_API_PORT` (default `3131`) can be overridden at compile time via
`-DBG_SANDBOX_API_PORT=<port>` in `CMakeLists.txt`.
---
### ✨ New feature: Password Manager
A fully integrated password manager with a secure encrypted vault, built directly
into BastionGuard. All credentials are stored locally — no cloud, no third-party
service.
---
#### Encryption & Storage (`PasswordVault.cpp`, `secrets.enc`)
- **AES-256-GCM** — all passwords are stored in a single encrypted file
`~/.config/BastionGuard/password_manager/secrets.enc`. The file contains the
ciphertext, a 12-byte random nonce, and a 16-byte GCM authentication tag.
- **PBKDF2-SHA256 key derivation** — the AES-256 key is derived from the master
password using PBKDF2-SHA256 with 100,000 iterations and a 16-byte random salt
regenerated on every write. Brute-force resistant even with direct file access.
- **Tamper detection** — the GCM authentication tag is verified on every decrypt.
Any modification to the ciphertext, nonce, salt, or tag makes the vault
**permanently unreadable**. This is enforced at the cryptographic level.
- **`master.json`** — stores only the PBKDF2 hash and salt of the master password.
The plaintext is never written to disk. Comparison uses constant-time logic to
prevent timing-based brute-force attacks.
- **Atomic write**`secrets.enc` is written via `rename()` on a `.tmp` file.
No corruption can occur on crash or power loss mid-write.
- **Replaced libsecret per-entry storage** — the previous architecture stored one
secret per credential in GNOME Keyring via D-Bus. With 1,500 credentials this
caused high gnome-keyring CPU usage and write failures due to D-Bus queue
saturation. Now a single file write replaces all 1,500 D-Bus roundtrips.
---
#### Master password (`PasswordManagerPage.cpp`)
- **First-run wizard** — on first open, the user creates a master password with a
real-time strength indicator: Weak (red) / Medium (orange) / Strong (green).
Minimum 8 characters; confirmation field required.
- **Re-lock / unlock** — the RAM cache is cleared on lock; no plaintext remains in
memory when the vault is closed. An async warm-up thread reloads all secrets
from `secrets.enc` on the next unlock.
---
#### Performance (`PasswordVault.cpp`)
- **In-memory RAM cache** — on unlock, all secrets are loaded from `secrets.enc`
into an `unordered_map<id, plaintext>` protected by a `std::mutex`. Subsequent
`getSecretAsync()` calls are answered from cache — zero D-Bus roundtrips per
lookup.
- **Async warm-up** — a background thread decrypts and populates the cache
immediately after unlock. `cacheReady_` flag set on completion; the UI shows
"loading cache…" in the state badge during warm-up.
- **Bulk import O(n)**`addEntriesBulk()` writes the index JSON once for the
entire batch instead of once per entry (was O(n²)). Background thread persists
secrets to `secrets.enc` with a single encrypt + write operation.
- **`getSecretAsync()` — three-level lookup:**
1. Cache hit → instant response via `Glib::signal_idle`
2. Warm-up in progress → 50 ms polling via `Glib::signal_timeout` (max 5 s)
3. Cache ready but id not found → fallback for edge cases
---
#### Browser import (`PasswordImporter.cpp`, `PasswordImportDialog.cpp`)
- **Supported formats** — Chrome / Chromium, Edge (identical CSV format), Firefox
(Lockwise export), Safari.
- **Auto-detect** — browser identified from the CSV header line, case-insensitive,
BOM-aware (UTF-8 BOM stripped). Robust to column order variations.
- **RFC 4180 parser** — custom tokeniser handles quoted fields, embedded commas,
escaped double-quotes (`""`), and Windows `\r\n` line endings.
- **Preview dialog** — first 50 rows displayed before confirming; full import
(all rows) runs in a background thread with a live progress bar.
- **Progress bar** — updated via `Glib::Dispatcher` from the import thread.
The UI never blocks regardless of import size.
---
#### Vault view & export (`PasswordVaultView.cpp`)
- **Vault view dialog** — searchable table showing Name, Username, URL,
Last updated. Full-text filter updates live as the user types.
- **Per-entry detail** — clicking 👁 opens a detail popup with all fields
(name, username, URL, password, notes, created/updated). Password field is
selectable for copy-paste.
- **CSV export** — runs on a background thread via `Glib::Dispatcher`. Format:
`name,url,username,password,notes` — RFC 4180 compliant with proper quoting.
File-save dialog with `.csv` filter.
---
#### UI & security indicators
- **Security banner** — always visible at the top of the manager page. Explains
AES-256-GCM protection and states that any file tampering renders the vault
permanently unreadable.
- **State badge** — top-right corner:
- 🟢 **Green** (`alert-success`) when vault is **locked** — credentials safe,
no plaintext in memory.
- 🔴 **Red** (`alert-danger`) when vault is **unlocked** — vault open, credentials
accessible in RAM.
- **Two-row toolbar** — row 1: Unlock / Lock / state badge;
row 2: + New / ⬆ Import / 🗄 Vault / ↺ Refresh / 🗑 Delete-all / 🔍 Search.
- **Delete-all** — double confirmation dialog (WARNING → ERROR level) plus async
background removal of `secrets.enc`.
---
#### Bug fixes
| Component | Bug | Fix |
|---|---|---|
| `PasswordVault.cpp` | `secret_password_store` fired 1,500× in a loop, saturating D-Bus queue | Replaced per-entry libsecret with single AES-256-GCM file write |
| `PasswordVault.cpp` | `secret_password_lookup_sync` blocked GTK4 main loop on "Show password" | Replaced with in-memory RAM cache; fallback uses async `secret_password_lookup` |
| `PasswordVault.cpp` | `deleteAllEntries` froze UI (N × `clear_sync` on main thread) | Async background thread; index cleared atomically before keyring cleanup |
| `PasswordImportDialog.cpp` | SEGV on import: `dialog_->hide()` called after `delete dialog` | `onImportDone` no longer calls `hide()`; caller hides before `delete` |
| `PasswordVault.cpp` | Passwords empty after re-lock/unlock (cache not populated) | `warmUpCache()` thread started immediately after every `unlock()` |
---
### ✨ New feature: Dark mode & theme switcher
---
#### Theme files
- **`BastionGuard-dark.css`** — full dark theme. Background `#1a1d23`, text
`#e4e7eb`, cards `#23272e`, sidebar `#16191f`. Covers all UI components
including sidebar, cards, buttons, inputs, badges, and separators.
- **`BastionGuard.css`** — unchanged light theme, now the explicit default.
Background `#f8f9fa`, text `#212529`.
---
#### Runtime switching (`DashboardPage.cpp`)
- **☀ / 🌙 buttons** — two flat icon buttons in the Dashboard footer, left of the
update badge. Clicking applies the selected theme instantly via
`Gtk::StyleContext::add_provider_for_display()` at
`GTK_STYLE_PROVIDER_PRIORITY_USER` — no restart required.
- **Active highlight** — the button for the currently active theme receives the
CSS class `theme-btn-active` (full opacity); the inactive button is dimmed
(`opacity: 0.5`).
- **Preference saved** — theme choice written to
`~/.config/BastionGuard/theme.conf` on every click. File contains a single
word: `light` or `dark`.
---
#### Startup restore (`StyleProvider.cpp`)
- **`read_saved_theme()`** — new helper function reads
`~/.config/BastionGuard/theme.conf` before the main window is shown.
Returns `"dark"` or `"light"` (default if file absent or value unrecognised).
- **`load_style()` updated** — selects `BastionGuard-dark.css` or
`BastionGuard.css` based on the saved theme. Search order: `data/` (local
build), then `DATA_DIR` (installed path). Falls back to light theme if the
requested CSS file is not found — no crash, no blank window.
- **First launch** — if `theme.conf` does not exist, light theme is used.
No migration required from previous installations.
---
#### Settings → Options (`SettingsPage.cpp`)
- **Theme selector**`Gtk::ComboBoxText` with two entries: ☀ Chiaro (Light)
and 🌙 Scuro (Dark). Shows the current saved theme on open.
- **Preview label** — describes the selected theme (background colour, text
colour) and updates live as the user changes the selection.
- **"Applica tema" button** — loads the CSS file and applies it immediately via
`add_provider_for_display`. Shows a confirmation dialog on success; shows an
error dialog if the CSS file is not found. Saves preference to `theme.conf`.
---
#### Bug fixes
| Component | Bug | Fix |
|---|---|---|
| `StyleProvider.cpp` | App always started in light mode regardless of saved preference | `load_style()` now reads `theme.conf` before selecting the CSS file |
| `DashboardPage.cpp` | Theme buttons had no visual feedback for current selection | `theme-btn-active` CSS class added/removed on click and at startup |
| `IdentityLeakPage.cpp` | Fix dark mode visualization |
| `BankPage.cpp` | Fix update in silent mode |
---
#### Compatibility
- `StyleProvider.hpp` public API unchanged (`load_style()` signature identical).
- `BastionGuard.css` unchanged — existing installations continue to work without
any `theme.conf` file.
- `BastionGuard-dark.css` is a new optional file; absence does not affect the
light theme.
---

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,7 @@ Detailed instructions for compiling and installing BastionGuard are available in
Please refer to:
https://bastionguard.eu/documentation/bastionguard-documentation/
https://bastionguard.eu/documentation/
Section: **Technical Documentation – Application Install**

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<!--
BastionGuard™ — PolicyKit action per installazione CA
Installare in: /usr/share/polkit-1/actions/eu.bastionguard.install-ca.policy
-->
<policyconfig>
<vendor>BastionGuard</vendor>
<vendor_url>https://bastionguard.eu</vendor_url>
<action id="eu.bastionguard.install-ca">
<description>Installa il certificato CA di BastionGuard</description>
<message>BastionGuard ha bisogno di installare il suo certificato di sicurezza nel sistema per proteggere le tue sessioni bancarie. Questa operazione viene eseguita una sola volta.</message>
<icon_name>security-high</icon_name>
<defaults>
<!-- Sessione locale interattiva: chiede password una volta per sessione -->
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">/usr/share/BastionGuard/data/scripts/install-ca-system.sh</annotate>
<annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
</action>
</policyconfig>

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<policyconfig>
<vendor>BastionGuard</vendor>
<vendor_url>https://www.codelinsoft.it</vendor_url>
<action id="org.bastionguard.activation">
<description>Refresh BastionGuard activation hardware IDs and save the activation key</description>
<message>Authentication is required to refresh the BastionGuard activation hardware IDs or save the activation key system-wide.</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">@CMAKE_INSTALL_FULL_BINDIR@/bastionguard-activation-helper</annotate>
<annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
</action>
</policyconfig>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

BIN
data/bank-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

202
data/bank-icon.svg Normal file
View file

@ -0,0 +1,202 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
version="1.0"
id="Layer_1"
width="800.00745"
height="800"
viewBox="0 0 64.000596 64"
enable-background="new 0 0 64 64"
xml:space="preserve"
sodipodi:docname="bank-icon.svg"
inkscape:export-filename="bank-icon-new.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs12" /><sodipodi:namedview
id="namedview12"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"><inkscape:page
x="0"
y="0"
width="64.000595"
height="64"
id="page1"
margin="0"
bleed="0" /></sodipodi:namedview>
<g
id="g12">
<g
id="g3">
<rect
x="18"
y="25"
fill="#506C7F"
width="4"
height="29"
id="rect1"
style="fill:#000080;fill-opacity:1" />
<rect
x="30"
y="25"
fill="#506C7F"
width="4"
height="29"
id="rect2"
style="fill:#000080;fill-opacity:1" />
<rect
x="42"
y="25"
fill="#506C7F"
width="4"
height="29"
id="rect3"
style="fill:#000080;fill-opacity:1" />
</g>
<g
id="g7">
<rect
x="48"
y="25"
fill="#b4ccb9"
width="4"
height="29"
id="rect4" />
<rect
x="24"
y="25"
fill="#b4ccb9"
width="4"
height="29"
id="rect5" />
<rect
x="36"
y="25"
fill="#b4ccb9"
width="4"
height="29"
id="rect6" />
<rect
x="12"
y="25"
fill="#b4ccb9"
width="4"
height="29"
id="rect7" />
</g>
<g
id="g8">
<path
fill="#F9EBB2"
d="m 8,56 c -1.104,0 -2,0.896 -2,2 h 52 c 0,-1.104 -0.895,-2 -2,-2 z"
id="path7"
style="fill:#b4ccb9;fill-opacity:1" />
<path
fill="#F9EBB2"
d="M 60,60 H 4 c -1.104,0 -2,0.896 -2,2 h 60 c 0,-1.104 -0.895,-2 -2,-2 z"
id="path8"
style="fill:#b4ccb9;fill-opacity:1" />
</g>
<path
fill="#F9EBB2"
d="m 4,23 h 56 c 0.893,0 1.684,-0.601 1.926,-1.461 0.24,-0.86 -0.125,-1.785 -0.889,-2.248 l -28,-17 C 32.725,2.1 32.365,2 32,2 31.633,2 31.275,2.1 30.963,2.29 L 2.961,19.291 C 2.197,19.754 1.832,20.679 2.073,21.538 2.315,22.399 3.107,23 4,23 Z"
id="path9"
style="fill:#b4ccb9;fill-opacity:1" />
<g
id="g11">
<path
fill="#394240"
d="m 60,58 c 0,-2.209 -1.791,-4 -4,-4 H 54 V 25 h 6 c 1.795,0 3.369,-1.194 3.852,-2.922 0.484,-1.728 -0.242,-3.566 -1.775,-4.497 l -28,-17 C 33.439,0.193 32.719,0 32,0 31.281,0 30.562,0.193 29.924,0.581 l -28,17 c -1.533,0.931 -2.26,2.77 -1.775,4.497 C 0.632,23.806 2.207,25 4,25 h 6 V 54 H 8 c -2.209,0 -4,1.791 -4,4 -2.209,0 -4,1.791 -4,4 v 2 h 64 v -2 c 0,-2.209 -1.791,-4 -4,-4 z M 4,23 C 3.107,23 2.315,22.399 2.074,21.538 1.833,20.679 2.198,19.754 2.962,19.291 l 28,-17.001 C 31.275,2.1 31.635,2 32,2 c 0.367,0 0.725,0.1 1.039,0.291 l 28,17 c 0.764,0.463 1.129,1.388 0.887,2.248 C 61.686,22.399 60.893,23 60,23 Z m 48,2 V 54 H 48 V 25 Z m -6,0 V 54 H 42 V 25 Z m -6,0 V 54 H 36 V 25 Z m -6,0 V 54 H 30 V 25 Z m -6,0 V 54 H 24 V 25 Z m -6,0 V 54 H 18 V 25 Z m -6,0 V 54 H 12 V 25 Z M 8,56 h 48 c 1.105,0 2,0.896 2,2 H 6 c 0,-1.104 0.896,-2 2,-2 z m -6,6 c 0,-1.104 0.896,-2 2,-2 h 56 c 1.105,0 2,0.896 2,2 z"
id="path10" />
<path
fill="#394240"
d="m 32,9 c -2.762,0 -5,2.238 -5,5 0,2.762 2.238,5 5,5 2.762,0 5,-2.238 5,-5 0,-2.762 -2.238,-5 -5,-5 z m 0,8 c -1.656,0 -3,-1.343 -3,-3 0,-1.657 1.344,-3 3,-3 1.658,0 3,1.343 3,3 0,1.657 -1.342,3 -3,3 z"
id="path11" />
</g>
<circle
fill="#F76D57"
cx="32"
cy="14"
r="3"
id="circle11"
style="fill:#000080;fill-opacity:1" />
</g><text
xml:space="preserve"
style="font-size:2.34666px;font-family:Azonix;-inkscape-font-specification:'Azonix, Normal';text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;shape-subtract:url(#path11);display:inline;fill:#000000;stroke:#ffffff;stroke-width:0.0212695;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:0.0425394, 0.0212695;paint-order:stroke fill markers"
id="text1"
y="57.973301"
x="22.053303"><tspan
sodipodi:role="line"
id="tspan1"
style="display:inline;fill:#000000;stroke-width:0.0212696"
x="22.053303"
y="57.973301">BASTIONGUARD</tspan></text><path
fill="#394240"
d="m 40.800001,32.32 c -2.762,0 -5,2.238 -5,5 0,2.762 2.238,5 5,5 2.762,0 5,-2.238 5,-5 0,-2.762 -2.238,-5 -5,-5 z m 0,8 c -1.656,0 -3,-1.343 -3,-3 0,-1.657 1.344,-3 3,-3 1.658,0 3,1.343 3,3 0,1.657 -1.342,3 -3,3 z"
id="path11-6" />
<path
d="m 51.173838,49.169718 h -16.44227 c -1.623538,0 -2.942005,-1.320674 -2.942005,-2.946928 V 35.439632 c 0,-1.626255 1.318467,-2.946928 2.942005,-2.946928 h 16.44227 c 1.623538,0 2.942005,1.320673 2.942005,2.946928 v 10.779645 c 0,1.629767 -1.314961,2.950441 -2.942005,2.950441 z"
fill="#248cbe"
id="path1"
style="stroke-width:0.0350949" /><path
d="M 31.789563,36.212366 H 54.11935 v 3.375445 H 31.789563 Z"
fill="#183351"
id="path2"
style="stroke-width:0.0350949" /><path
d="m 40.194792,44.273391 h -6.161029 c -0.424294,0 -0.771444,-0.34773 -0.771444,-0.772734 0,-0.425004 0.34715,-0.772734 0.771444,-0.772734 h 6.161029 c 0.424294,0 0.771444,0.34773 0.771444,0.772734 0,0.425004 -0.34715,0.772734 -0.771444,0.772734 z m 4.677754,2.437626 H 34.033763 c -0.424294,0 -0.771444,-0.34773 -0.771444,-0.772734 0,-0.425004 0.34715,-0.772735 0.771444,-0.772735 h 10.838783 c 0.424294,0 0.771443,0.347731 0.771443,0.772735 0,0.425004 -0.347149,0.772734 -0.771443,0.772734 z"
fill="#fbfaee"
id="path3"
style="stroke-width:0.0350949" /><path
d="M 60.245313,54.663157 H 43.803044 c -1.623538,0 -2.942005,-1.320673 -2.942005,-2.946928 V 40.933071 c 0,-1.626254 1.318467,-2.946928 2.942005,-2.946928 h 16.442269 c 1.623539,0 2.942006,1.320674 2.942006,2.946928 v 10.779645 c 0,1.629768 -1.314961,2.950441 -2.942006,2.950441 z"
fill="#f5db6f"
id="path4"
style="stroke-width:0.0350949" /><path
d="M 57.177072,46.921763 H 43.105238 c -0.424294,0 -0.771443,-0.34773 -0.771443,-0.772734 0,-0.425004 0.347149,-0.772735 0.771443,-0.772735 h 14.071834 c 0.424294,0 0.771443,0.347731 0.771443,0.772735 0,0.425004 -0.347149,0.772734 -0.771443,0.772734 z"
fill="#aeb8c4"
id="path5"
style="stroke-width:0.0350949" /><path
d="m 49.266268,49.766831 h -6.16103 c -0.424294,0 -0.771443,-0.347731 -0.771443,-0.772735 0,-0.425004 0.347149,-0.772734 0.771443,-0.772734 h 6.164536 c 0.424294,0 0.771444,0.34773 0.771444,0.772734 -0.0035,0.425004 -0.350656,0.772735 -0.77495,0.772735 z m 4.677754,2.437626 H 43.105238 c -0.424294,0 -0.771443,-0.347731 -0.771443,-0.772735 0,-0.425004 0.347149,-0.772734 0.771443,-0.772734 h 10.838784 c 0.424294,0 0.771443,0.34773 0.771443,0.772734 0,0.425004 -0.347149,0.772735 -0.771443,0.772735 z"
fill="#fbfaee"
id="path6"
style="stroke-width:0.0350949" /><path
d="M 47.432336,43.869462 H 43.62421 c -0.711832,0 -1.290415,-0.579551 -1.290415,-1.292574 V 40.792574 C 42.333795,40.079551 42.912378,39.5 43.62421,39.5 h 3.808126 c 0.711832,0 1.290415,0.579551 1.290415,1.292574 v 1.784314 c 0,0.713023 -0.578583,1.292574 -1.290415,1.292574 z"
fill="#f3c262"
id="path7-3"
style="stroke-width:0.0350949" /><path
d="M 48.722751,40.982245 H 47.52 V 39.5 h -1.188724 v 4.369462 H 47.52 v -1.675429 h 1.202751 z M 43.652262,39.5 v 1.482245 h -1.318467 v 1.211788 h 1.318467 v 1.675429 h 1.188725 V 39.5 Z"
fill="#f7a04d"
id="path8-6"
style="stroke-width:0.0350949" /><path
d="M 63.187319,45.889109 V 42.59445 C 60.36103,42.58391 57.990594,40.61344 57.36292,37.972093 h -3.348767 c 0.67326,4.46781 4.530478,7.906479 9.173166,7.917016 z"
fill="#f7f9dd"
id="path9-7"
style="stroke-width:0.0350949" /><text
xml:space="preserve"
style="font-size:1.06667px;font-family:Azonix;-inkscape-font-specification:'Azonix, Normal';text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;fill:#000000;stroke:#ffffff;stroke-width:0.0212695;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:0.0425395, 0.0212695;paint-order:stroke fill markers"
x="42.163498"
y="56.800003"
id="text2"><tspan
sodipodi:role="line"
id="tspan2"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.06667px;font-family:sans-serif;-inkscape-font-specification:sans-serif;fill:#000000;stroke-width:0.0212695"
x="42.163498"
y="56.800003">TM</tspan></text><text
xml:space="preserve"
style="font-size:2.34666px;font-family:Azonix;-inkscape-font-specification:'Azonix, Normal';text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;shape-subtract:url(#path11);display:inline;fill:#000000;stroke:#ffffff;stroke-width:0.0212695;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:0.0425394, 0.0212695;paint-order:stroke fill markers"
id="text1-0"
y="61.989365"
x="22.311258"><tspan
sodipodi:role="line"
id="tspan1-6"
style="display:inline;fill:#000000;stroke-width:0.0212696"
x="22.311258"
y="61.989365">SECURE BANK</tspan></text></svg>

After

Width:  |  Height:  |  Size: 9.1 KiB

View file

@ -1,5 +1,5 @@
{
"manifest_version": 3,
"manifest_version": 2,
"name": "BastionGuard Mail Security",
"version": "1.0.0",
"description": "BastionGuard: iniezione firma aziendale su ogni email in uscita.",
@ -10,8 +10,9 @@
"96": "icons/logo.png"
},
"background": {
"scripts": ["background.js"]
},
"scripts": ["background.js"],
"persistent": true
},
"permissions": [
"compose",
"messagesRead",

50
data/icons/backup.svg Normal file
View file

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
width="800"
height="800"
viewBox="0 0 20 20"
version="1.1"
id="svg1"
sodipodi:docname="backup.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1">
<inkscape:page
x="0"
y="0"
width="20"
height="20"
id="page2"
margin="0"
bleed="0" />
</sodipodi:namedview>
<rect
x="0"
fill="none"
width="20"
height="20"
id="rect1"
y="0" />
<g
id="g1"
style="fill:#ffffff">
<path
d="m 13.65,2.88 c 3.93,2.01 5.48,6.84 3.47,10.77 -2.01,3.93 -6.83,5.48 -10.77,3.47 -1.87,-0.96 -3.2,-2.56 -3.86,-4.4 l 1.64,-1.03 c 0.45,1.57 1.52,2.95 3.08,3.76 3.01,1.54 6.69,0.35 8.23,-2.66 C 16.99,9.78 15.8,6.1 12.79,4.55 9.78,3.01 6.1,4.2 4.56,7.21 L 6.44,8.18 1.49,11.26 1.1,5.44 2.88,6.35 C 4.9,2.4 9.75,0.89 13.65,2.88 Z M 9.29,10.71 C 9.11,10.53 9,10.28 9,10 9,9.93 9.03,9.88 9.04,9.81 H 9.03 L 10,5 10.97,9.81 14,13 9.5,10.88 9.52,10.86 C 9.44,10.82 9.36,10.77 9.29,10.71 Z"
id="path1"
style="fill:#ffffff" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

54
data/icons/password.svg Normal file
View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
width="666.66663"
height="600"
viewBox="0 0 19.999999 18"
fill="none"
version="1.1"
id="svg2"
sodipodi:docname="password.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<sodipodi:namedview
id="namedview2"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1">
<inkscape:page
x="0"
y="0"
width="19.999998"
height="18"
id="page2"
margin="0"
bleed="0" />
</sodipodi:namedview>
<path
style="baseline-shift:baseline;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:#ffffff;stroke-linecap:round;stroke-linejoin:round;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
d="M 3.0000001,0 C 1.3549905,0 1.412796e-7,1.3549904 1.412796e-7,3 v 5 c 0,1.645025 1.3550084587204,3 2.9999999587204,3 h 5.875 a 1,1 0 0 0 1,-1 1,1 0 0 0 -1,-1 h -5.875 c -0.5641485,0 -1,-0.435825 -1,-1 V 3 c 0,-0.5641304 0.4358696,-1 1,-1 H 17 c 0.564175,0 1,0.4358515 1,1 v 2.5 a 1,1 0 0 0 1,1 1,1 0 0 0 1,-1 V 3 C 20,1.3550085 18.645025,0 17,0 Z M 15,6 c -1.645007,0 -3,1.354993 -3,3 v 1 c -1.092707,0 -2,0.907293 -2,2 v 4 c 0,1.092707 0.907293,2 2,2 h 6 c 1.092707,0 2,-0.907293 2,-2 v -4 c 0,-1.092707 -0.907293,-2 -2,-2 V 9 C 18,7.354993 16.645007,6 15,6 Z m 0,2 c 0.564193,0 1,0.435807 1,1 v 1 H 14 V 9 c 0,-0.564193 0.435807,-1 1,-1 z m -3,4 h 1 4 1 v 4 h -6 z"
id="path1" />
<circle
cx="5.5"
cy="5.5"
r="1.5"
fill="#000000"
id="circle1"
style="fill:#ffffff" />
<circle
cx="10"
cy="5.5"
r="1.5"
fill="#000000"
id="circle2"
style="fill:#ffffff" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

43
data/icons/payments.svg Normal file
View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
width="666.66663"
height="533.33337"
viewBox="0 0 19.999999 16.000001"
fill="none"
version="1.1"
id="svg1"
sodipodi:docname="payments.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1">
<inkscape:page
x="0"
y="0"
width="19.999998"
height="16.000002"
id="page2"
margin="0"
bleed="0" />
</sodipodi:namedview>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 1.412796e-7,4.0000001 C 1.412796e-7,1.7908601 1.7908601,1.8324281e-7 4.0000001,1.8324281e-7 H 16 c 2.2091,0 4,1.79085991675719 4,3.99999991675719 v 0.5 c 0,0.27614 -0.2239,0.5 -0.5,0.5 H 0.50000014 c -0.27614,0 -0.4999999987204,-0.22386 -0.4999999987204,-0.5 z m 0.4999999987204,3 c -0.27614,0 -0.4999999987204,0.2239 -0.4999999987204,0.5 V 12 c 0,2.2091 1.7908599587204,4 3.9999999587204,4 H 16 c 2.2091,0 4,-1.7909 4,-4 V 7.5000001 c 0,-0.2761 -0.2239,-0.5 -0.5,-0.5 z M 11,11 c 0,-0.5523 0.4477,-1.0000001 1,-1.0000001 h 3 c 0.5523,0 1,0.4477001 1,1.0000001 0,0.5523 -0.4477,1 -1,1 h -3 c -0.5523,0 -1,-0.4477 -1,-1 z"
fill="#000000"
id="path1"
style="fill:#ffffff" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -1,9 +1,60 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.87988 18.1501V16.0801" stroke="#292D32" stroke-width="1.5" stroke-linecap="round"/>
<path d="M12 18.15V14.01" stroke="#292D32" stroke-width="1.5" stroke-linecap="round"/>
<path d="M17.1201 18.1499V11.9299" stroke="#292D32" stroke-width="1.5" stroke-linecap="round"/>
<path d="M17.1199 5.8501L16.6599 6.3901C14.1099 9.3701 10.6899 11.4801 6.87988 12.4301" stroke="#292D32" stroke-width="1.5" stroke-linecap="round"/>
<path d="M14.1899 5.8501H17.1199V8.7701" stroke="#292D32" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 22H15C20 22 22 20 22 15V9C22 4 20 2 15 2H9C4 2 2 4 2 9V15C2 20 4 22 9 22Z" stroke="#292D32" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
width="716.66663"
height="716.66663"
viewBox="0 0 21.499999 21.499999"
fill="none"
version="1.1"
id="svg6"
sodipodi:docname="status.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs6" />
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1">
<inkscape:page
x="0"
y="0"
width="21.499998"
height="21.499998"
id="page2"
margin="0"
bleed="0" />
</sodipodi:namedview>
<path
style="baseline-shift:baseline;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:#000000;stroke-linecap:round;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
d="m 5.6289062,14.080078 a 0.75,0.75 0 0 0 -0.75,0.75 v 2.070313 a 0.75,0.75 0 0 0 0.75,0.75 0.75,0.75 0 0 0 0.75,-0.75 v -2.070313 a 0.75,0.75 0 0 0 -0.75,-0.75 z"
id="path1" />
<path
style="baseline-shift:baseline;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:#000000;stroke-linecap:round;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
d="m 10.75,12.009766 a 0.75,0.75 0 0 0 -0.75,0.75 v 4.140625 a 0.75,0.75 0 0 0 0.75,0.75 0.75,0.75 0 0 0 0.75,-0.75 v -4.140625 a 0.75,0.75 0 0 0 -0.75,-0.75 z"
id="path2" />
<path
style="baseline-shift:baseline;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:#000000;stroke-linecap:round;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
d="m 15.869141,9.929688 a 0.75,0.75 0 0 0 -0.75,0.75 v 6.220703 a 0.75,0.75 0 0 0 0.75,0.75 0.75,0.75 0 0 0 0.75,-0.75 v -6.220703 a 0.75,0.75 0 0 0 -0.75,-0.75 z"
id="path3" />
<path
style="baseline-shift:baseline;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:#000000;stroke-linecap:round;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
d="M 15.810547,3.8515625 A 0.75,0.75 0 0 0 15.298828,4.1132812 L 14.839844,4.6523437 C 12.391515,7.5135282 9.108518,9.540706 5.4492187,10.453125 a 0.75,0.75 0 0 0 -0.546875,0.908203 0.75,0.75 0 0 0 0.9082032,0.546875 C 9.771287,10.920622 13.328798,8.7257687 15.980469,5.6269531 L 16.441406,5.0859375 A 0.75,0.75 0 0 0 16.355469,4.0292969 0.75,0.75 0 0 0 15.810547,3.8515625 Z"
id="path4" />
<path
style="baseline-shift:baseline;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:#000000;stroke-linecap:round;stroke-linejoin:round;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
d="m 12.939453,3.8496094 a 0.75,0.75 0 0 0 -0.75,0.75 0.75,0.75 0 0 0 0.75,0.75 h 2.179688 v 2.1699219 a 0.75,0.75 0 0 0 0.75,0.75 0.75,0.75 0 0 0 0.75,-0.75 V 4.5996094 a 0.750075,0.750075 0 0 0 -0.75,-0.75 z"
id="path5" />
<path
style="baseline-shift:baseline;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:#000000;stroke-linecap:round;stroke-linejoin:round;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
d="M 7.75,1.2831577e-8 C 5.15,1.2831577e-8 3.1651686,0.52233141 1.84375,1.84375 0.52233141,3.1651686 1.2831577e-8,5.15 1.2831577e-8,7.75 v 6 C 1.2831577e-8,16.35 0.52233141,18.334831 1.84375,19.65625 3.1651686,20.977669 5.15,21.5 7.75,21.5 h 6 c 2.6,0 4.584831,-0.522331 5.90625,-1.84375 C 20.977669,18.334831 21.5,16.35 21.5,13.75 v -6 C 21.5,5.15 20.977669,3.1651686 19.65625,1.84375 18.334831,0.52233141 16.35,1.2831577e-8 13.75,1.2831577e-8 Z M 7.75,1.5 h 6 c 2.4,0 3.915169,0.4776686 4.84375,1.40625 C 19.522331,3.8348314 20,5.35 20,7.75 v 6 c 0,2.4 -0.477669,3.915169 -1.40625,4.84375 C 17.665169,19.522331 16.15,20 13.75,20 h -6 C 5.35,20 3.8348314,19.522331 2.90625,18.59375 1.9776686,17.665169 1.5,16.15 1.5,13.75 v -6 C 1.5,5.35 1.9776686,3.8348314 2.90625,2.90625 3.8348314,1.9776686 5.35,1.5 7.75,1.5 Z"
id="path6" />
</svg>

Before

Width:  |  Height:  |  Size: 961 B

After

Width:  |  Height:  |  Size: 4.2 KiB

Before After
Before After

View file

@ -4,15 +4,60 @@ set -e
LOG_DIR="/var/log/BastionGuard"
LOG_FILE="$LOG_DIR/phishing_updater.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
PHISH_SYS="/usr/share/BastionGuard/data/phishing"
DNSMASQ_CONF="/etc/dnsmasq.d/BastionGuard-blacklist.conf"
mkdir -p "$LOG_DIR"
mkdir -p "$LOG_DIR" "$PHISH_SYS"
echo "[$DATE] Avvio aggiornamento blacklist..." >> "$LOG_FILE"
/usr/bin/BastionGuard --update-phish >> "$LOG_FILE" 2>&1
# 1. Installa blacklist da /tmp (preparate dal backend user-space)
if [[ -f "/tmp/bastionguard-blacklist.txt" ]]; then
install -m 0644 /tmp/bastionguard-blacklist.txt \
"$PHISH_SYS/blacklist.txt"
echo "[$DATE] blacklist.txt installata" >> "$LOG_FILE"
fi
if systemctl is-active --quiet BastionGuard-phishing-scanner.service; then
echo "[$DATE] Servizio attivo, riavvio..." >> "$LOG_FILE"
systemctl restart BastionGuard-phishing-scanner.service
if [[ -f "/tmp/bastionguard-blacklist-reduce.txt" ]]; then
install -m 0644 /tmp/bastionguard-blacklist-reduce.txt \
"$PHISH_SYS/blacklist-reduce.txt"
fi
# 2. Merge whitelist utente → copia in sys se esiste
REAL_USER="${SUDO_USER:-$(logname 2>/dev/null || echo '')}"
if [[ -n "$REAL_USER" ]]; then
USER_HOME=$(getent passwd "$REAL_USER" | cut -d: -f6)
WL_TXT="$USER_HOME/.local/share/BastionGuard/phishing/whitelist.txt"
if [[ -f "$WL_TXT" ]]; then
install -m 0644 "$WL_TXT" "$PHISH_SYS/whitelist.txt"
echo "[$DATE] whitelist utente copiata in sys ($WL_TXT)" >> "$LOG_FILE"
fi
fi
# 3. Installa config dnsmasq se preparata dal backend
DNSMASQ_OK=0
if [[ -f "/tmp/BastionGuard-dnsmasq-blacklist.conf" ]]; then
install -m 0644 /tmp/BastionGuard-dnsmasq-blacklist.conf \
"$DNSMASQ_CONF"
echo "[$DATE] dnsmasq conf installata" >> "$LOG_FILE"
if dnsmasq --test > /tmp/BastionGuard-dnsmasq.log 2>&1; then
DNSMASQ_OK=1
else
echo "[$DATE] ⚠ dnsmasq --test fallito, skip reload" >> "$LOG_FILE"
fi
fi
# 4. Riavvia dnsmasq e BastionGuard-phishing-scanner in parallelo
SCANNER_ACTIVE=0
systemctl is-active --quiet BastionGuard-phishing-scanner.service && SCANNER_ACTIVE=1
if [[ "$DNSMASQ_OK" -eq 1 || "$SCANNER_ACTIVE" -eq 1 ]]; then
[[ "$DNSMASQ_OK" -eq 1 ]] && systemctl restart dnsmasq 2>/dev/null &
[[ "$SCANNER_ACTIVE" -eq 1 ]] && systemctl restart BastionGuard-phishing-scanner.service 2>/dev/null &
wait
[[ "$DNSMASQ_OK" -eq 1 ]] && echo "[$DATE] dnsmasq ricaricato" >> "$LOG_FILE"
[[ "$SCANNER_ACTIVE" -eq 1 ]] && echo "[$DATE] Scanner riavviato" >> "$LOG_FILE"
fi
echo "[$DATE] Aggiornamento completato" >> "$LOG_FILE"

View file

@ -0,0 +1,195 @@
#!/usr/bin/env bash
# ============================================================================
# BastionGuard - Riavvio dei servizi --user per TUTTI gli utenti
# ----------------------------------------------------------------------------
# Pensato per essere chiamato dal pacchetto Debian (postinst, triggers,
# o un dpkg trigger su /usr/lib/systemd/user/) dopo un upgrade dei binari
# o delle unit user-level di BastionGuard.
#
# Lo script gira SEMPRE come root e:
# 1. Fa "systemctl --global daemon-reload" così le unit installate in
# /usr/lib/systemd/user/ vengono ripescate dai futuri manager utente.
# 2. Trova TUTTI gli utenti con un user-manager systemd attivo:
# - sessioni attive (loginctl list-users)
# - utenti lingering (loginctl show-user --property=Linger)
# - utenti con /run/user/<uid> esistente
# 3. Per ognuno fa:
# - daemon-reload sul SUO bus (--global non aggiorna i manager già vivi)
# - try-restart di tutte le unit BastionGuard-*.service realmente
# installate per quell'utente
# 4. Salta utenti di sistema (UID < 1000) e utenti senza /run/user/<uid>.
#
# Exit code: sempre 0 (non blocca dpkg --configure).
#
# Posizione: /usr/share/BastionGuard/data/scripts/
# Esempio di chiamata da debian/postinst:
#
# if [ "$1" = "configure" ] || [ "$1" = "triggered" ]; then
# /usr/share/BastionGuard/data/scripts/BastionGuard-restart-user-services.sh || true
# fi
# ============================================================================
set -u
# ----------------------------------------------------------------------------
# Lista delle unit --user di BastionGuard.
# Tieni allineato con i .service spediti in /usr/lib/systemd/user/.
# ----------------------------------------------------------------------------
ALL_SERVICES=(
"BastionGuard-cef.service"
"BastionGuard-mailproxy.service"
"BastionGuard-pacd.service"
"BastionGuard-phishing-scanner.service"
"BastionGuard-phishing-updater.service"
"BastionGuard-privacyd.service"
"BastionGuard-ransomware-alert.service"
"BastionGuard-ransomware-realtime-alert.service"
"BastionGuard-ransomware-realtime.service"
"BastionGuard-ransomware-scanner.service"
"BastionGuard-usbd.service"
"BastionGuard-useragent.service"
)
# ----------------------------------------------------------------------------
# Logging (stderr, prefissato, no colori per non sporcare apt)
# ----------------------------------------------------------------------------
log() { printf '[BastionGuard] %s\n' "$*" >&2; }
warn() { printf '[BastionGuard] WARN: %s\n' "$*" >&2; }
err() { printf '[BastionGuard] ERR : %s\n' "$*" >&2; }
# ----------------------------------------------------------------------------
# Prerequisiti
# ----------------------------------------------------------------------------
if ! command -v systemctl >/dev/null 2>&1; then
log "systemctl non presente, salto il riavvio dei servizi user."
exit 0
fi
# In chroot/container /run/systemd/system non esiste: niente da fare.
if [[ ! -d /run/systemd/system ]]; then
log "systemd non in esecuzione (chroot/container?), salto."
exit 0
fi
if [[ "$EUID" -ne 0 ]]; then
err "Questo script va eseguito come root (chiamato dal package manager)."
exit 0
fi
# UID minimo "umano". Standard è 1000 su Debian/Ubuntu/Fedora/openSUSE/Arch,
# ma rispettiamo /etc/login.defs se diverso.
UID_MIN=1000
if [[ -r /etc/login.defs ]]; then
_u="$(awk '/^[[:space:]]*UID_MIN/ {print $2; exit}' /etc/login.defs 2>/dev/null || true)"
[[ "$_u" =~ ^[0-9]+$ ]] && UID_MIN="$_u"
fi
# ----------------------------------------------------------------------------
# Step 1: daemon-reload globale (futuri manager utente).
# ----------------------------------------------------------------------------
log "systemctl daemon-reload"
systemctl daemon-reload >/dev/null 2>&1 || \
warn "daemon-reload fallito (best-effort)"
# ----------------------------------------------------------------------------
# Step 2: enumerazione utenti con user-manager attivo.
# ----------------------------------------------------------------------------
declare -A USERS_SET=()
if command -v loginctl >/dev/null 2>&1; then
# Tutti gli utenti noti a logind
while IFS= read -r _user; do
[[ -z "$_user" ]] && continue
USERS_SET["$_user"]=1
done < <(loginctl list-users --no-legend 2>/dev/null | awk '{print $2}')
fi
# Utenti con /run/user/<uid>: cattura sia logged-in sia lingering.
for d in /run/user/*; do
[[ -d "$d" ]] || continue
uid="$(basename "$d")"
[[ "$uid" =~ ^[0-9]+$ ]] || continue
[[ "$uid" -lt $UID_MIN ]] && continue
user="$(getent passwd "$uid" | cut -d: -f1)"
[[ -n "$user" ]] && USERS_SET["$user"]=1
done
if [[ ${#USERS_SET[@]} -eq 0 ]]; then
log "Nessun utente con sessione/linger attivo: niente da riavviare."
exit 0
fi
# ----------------------------------------------------------------------------
# run_as_user <user> <systemctl args...>
#
# Esegue "systemctl --user <args>" nel contesto del manager utente di <user>.
# Stesso pattern di src/Backend.cpp (runuser ... systemctl --user) e
# src/wizard/wizard_setup.cpp (export XDG_RUNTIME_DIR/DBUS_SESSION_BUS_ADDRESS).
# ----------------------------------------------------------------------------
run_as_user() {
local user="$1"; shift
local uid
uid="$(id -u "$user" 2>/dev/null)" || return 2
[[ "$uid" -lt $UID_MIN ]] && return 3
[[ -d "/run/user/$uid" ]] || return 4
runuser -u "$user" -- env \
XDG_RUNTIME_DIR="/run/user/$uid" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
systemctl --user "$@"
}
# ----------------------------------------------------------------------------
# Step 3: per ogni utente, daemon-reload + try-restart delle unit installate.
# ----------------------------------------------------------------------------
total_users=0
ok_users=0
for user in "${!USERS_SET[@]}"; do
uid="$(id -u "$user" 2>/dev/null || true)"
if [[ -z "$uid" || "$uid" -lt $UID_MIN ]]; then
continue
fi
if [[ ! -d "/run/user/$uid" ]]; then
warn "Utente '$user' (uid=$uid) senza /run/user/$uid, salto."
continue
fi
total_users=$((total_users + 1))
log "→ Utente '$user' (uid=$uid)"
# daemon-reload del manager utente vivo
run_as_user "$user" daemon-reload >/dev/null 2>&1 || \
warn " daemon-reload utente fallito"
user_fail=0
user_done=0
for svc in "${ALL_SERVICES[@]}"; do
# L'unit è installata per questo utente?
if ! run_as_user "$user" list-unit-files "$svc" >/dev/null 2>&1; then
continue
fi
# try-restart: riavvia solo se è già in esecuzione. Più sicuro in
# postinst: non riaccende servizi che l'utente aveva fermato.
# Cambia in "restart" se vuoi forzare l'avvio.
if run_as_user "$user" try-restart "$svc" >/dev/null 2>&1; then
log " ✔ try-restart $svc"
user_done=$((user_done + 1))
else
warn " ✘ try-restart $svc fallito"
user_fail=$((user_fail + 1))
fi
done
if [[ $user_fail -eq 0 ]]; then
ok_users=$((ok_users + 1))
log " utente '$user': $user_done unit riavviate."
else
log " utente '$user': $user_done OK, $user_fail errori."
fi
done
log "Riepilogo: $ok_users/$total_users utenti gestiti senza errori."
exit 0

View file

@ -0,0 +1,106 @@
#!/usr/bin/env bash
# BastionGuard user-session watcher
# Monitors suspend/resume and lock/unlock events, then restarts BastionGuard user services.
set -u
RESTART_SCRIPT="${BG_RESTART_SCRIPT:-/usr/share/BastionGuard/data/scripts/BastionGuard-restart-user-services.sh}"
DEBOUNCE_SECONDS="${BG_RESTART_DEBOUNCE_SECONDS:-8}"
STAMP_FILE="${XDG_RUNTIME_DIR:-/tmp}/BastionGuard-user-session-watch.last"
log_msg() {
local msg="$1"
if command -v systemd-cat >/dev/null 2>&1; then
printf '%s\n' "$msg" | systemd-cat -t BastionGuard-user-session-watch -p info
else
printf '%s\n' "BastionGuard-user-session-watch: $msg" >&2
fi
}
restart_user_services() {
local reason="$1"
local now last
now="$(date +%s)"
last="0"
if [ -r "$STAMP_FILE" ]; then
last="$(cat "$STAMP_FILE" 2>/dev/null || printf '0')"
fi
case "$last" in
''|*[!0-9]*) last="0" ;;
esac
if [ $((now - last)) -lt "$DEBOUNCE_SECONDS" ]; then
log_msg "skip restart for '$reason' because debounce is active"
return 0
fi
printf '%s\n' "$now" > "$STAMP_FILE" 2>/dev/null || true
if [ ! -x "$RESTART_SCRIPT" ]; then
log_msg "restart script missing or not executable: $RESTART_SCRIPT"
return 0
fi
log_msg "restarting BastionGuard user services after: $reason"
"$RESTART_SCRIPT" --user "$reason" || log_msg "restart script returned a non-zero status for: $reason"
}
monitor_login1_sleep() {
dbus-monitor --system "type='signal',interface='org.freedesktop.login1.Manager',member='PrepareForSleep'" 2>/dev/null |
while IFS= read -r line; do
case "$line" in
*"boolean false"*) restart_user_services "resume" ;;
esac
done
}
monitor_login1_lock() {
dbus-monitor --system "type='signal',interface='org.freedesktop.login1.Session'" 2>/dev/null |
while IFS= read -r line; do
case "$line" in
*"member=Lock"*) restart_user_services "session-lock" ;;
*"member=Unlock"*) restart_user_services "session-unlock" ;;
esac
done
}
monitor_freedesktop_screensaver() {
dbus-monitor --session "type='signal',interface='org.freedesktop.ScreenSaver'" 2>/dev/null |
while IFS= read -r line; do
case "$line" in
*"member=ActiveChanged"*) restart_user_services "screensaver-active-changed" ;;
esac
done
}
monitor_gnome_screensaver() {
dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'" 2>/dev/null |
while IFS= read -r line; do
case "$line" in
*"member=ActiveChanged"*) restart_user_services "gnome-screensaver-active-changed" ;;
esac
done
}
cleanup() {
trap - INT TERM EXIT
jobs -p | xargs -r kill 2>/dev/null || true
}
trap cleanup INT TERM EXIT
if ! command -v dbus-monitor >/dev/null 2>&1; then
log_msg "dbus-monitor not found; install package 'dbus' or equivalent"
while :; do sleep 3600; done
fi
log_msg "watcher started"
monitor_login1_sleep &
monitor_login1_lock &
monitor_freedesktop_screensaver &
monitor_gnome_screensaver &
# Keep the service alive. If a monitor exits, systemd restarts this watcher.
wait -n

79
data/scripts/bank-helper Executable file
View file

@ -0,0 +1,79 @@
#!/usr/bin/env bash
# bank-helper — BastionGuard™
# Copia banks.json nella directory di sistema e aggiorna version.txt.
#
# Può essere invocato in due modi:
# 1. Direttamente da utente: bank-helper <sorgente> <url>
# → si auto-rilancia con sudo se non è già root
# 2. Tramite sudo (da BankPage): sudo bank-helper <sorgente> <url>
# → esegue direttamente senza dialog
#
# Argomenti:
# $1 percorso assoluto del file banks.json sorgente (utente)
# $2 URL da cui è stata scaricata la lista (scritto in version.txt)
set -euo pipefail
readonly DEST_DIR="/usr/share/BastionGuard/data/bank"
readonly DEST_FILE="${DEST_DIR}/banks.json"
readonly VERSION_FILE="${DEST_DIR}/version.txt"
# ── Auto-elevazione ──────────────────────────────────────────────────────────
# Se non siamo root, ci rilanciamo con sudo (che grazie al sudoers non
# chiederà password). Questo permette di invocare bank-helper direttamente
# dal terminale senza dover premettere "sudo".
if [[ $EUID -ne 0 ]]; then
exec sudo /usr/bin/bank-helper "$@"
fi
# ── Validazione argomenti ────────────────────────────────────────────────────
if [[ $# -ne 2 ]]; then
echo "Utilizzo: bank-helper <percorso_banks_json> <url_sorgente>" >&2
exit 1
fi
SOURCE_FILE="$1"
SOURCE_URL="$2"
# ── Controlli di sicurezza ───────────────────────────────────────────────────
# 1. Il file sorgente deve esistere ed essere un file regolare.
if [[ ! -f "${SOURCE_FILE}" ]]; then
echo "bank-helper: file sorgente non trovato: ${SOURCE_FILE}" >&2
exit 2
fi
# 2. Il percorso sorgente deve stare dentro la home dell'utente reale.
# SUDO_USER è impostato da sudo; se siamo root diretto usiamo LOGNAME/USER.
REAL_USER="${SUDO_USER:-${LOGNAME:-${USER:-}}}"
if [[ -z "${REAL_USER}" ]] || [[ "${REAL_USER}" == "root" ]]; then
# Fallback: accettiamo qualsiasi percorso se lanciato come root diretto
# (caso d'uso: script di packaging/CI).
true
else
REAL_HOME=$(getent passwd "${REAL_USER}" | cut -d: -f6)
RESOLVED_SOURCE=$(realpath -e "${SOURCE_FILE}" 2>/dev/null || true)
if [[ -z "${RESOLVED_SOURCE}" ]] || \
[[ "${RESOLVED_SOURCE}" != "${REAL_HOME}/"* ]]; then
echo "bank-helper: percorso sorgente non autorizzato: ${SOURCE_FILE}" >&2
exit 4
fi
fi
# 3. Il file deve sembrare JSON (primo byte '{').
FIRST_CHAR=$(head -c 1 "${SOURCE_FILE}")
if [[ "${FIRST_CHAR}" != "{" ]]; then
echo "bank-helper: il file sorgente non sembra JSON valido." >&2
exit 5
fi
# ── Copia ────────────────────────────────────────────────────────────────────
install -d -m 755 "${DEST_DIR}"
install -m 644 "${SOURCE_FILE}" "${DEST_FILE}"
# ── version.txt ──────────────────────────────────────────────────────────────
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
printf "URL: %s\nAggiornato il: %s\n" "${SOURCE_URL}" "${TIMESTAMP}" \
> "${VERSION_FILE}"
exit 0

0
data/scripts/enable-user-agents.sh Normal file → Executable file
View file

File diff suppressed because it is too large Load diff

BIN
data/secure.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

108
data/secure.svg Normal file
View file

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
width="699.53125"
height="493.125"
viewBox="0 0 895.4 631.2"
class="icon"
version="1.1"
id="svg9"
sodipodi:docname="secure.svg"
inkscape:export-filename="secure.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs9" />
<sodipodi:namedview
id="namedview9"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1">
<inkscape:page
x="0"
y="0"
width="895.40002"
height="631.20001"
id="page2"
margin="0"
bleed="0" />
</sodipodi:namedview>
<path
d="M 552.8,474.80001 H 83.899997 c -46.3,0 -83.9000000517578,-37.6 -83.9000000517578,-83.9 V 83.900006 C -3.0517578e-6,37.600006 37.599997,6.1035157e-6 83.899997,6.1035157e-6 H 552.8 C 599.1,6.1035157e-6 636.7,37.600006 636.7,83.900006 V 390.80001 c 0,46.4 -37.5,84 -83.9,84 z"
fill="#248cbe"
id="path1" />
<path
d="M -3.0517578e-6,105.90001 H 636.8 v 96.1 H -3.0517578e-6 Z"
fill="#183351"
id="path2" />
<path
d="M 239.7,335.40001 H 63.999997 c -12.1,0 -22,-9.9 -22,-22 0,-12.1 9.9,-22 22,-22 H 239.7 c 12.1,0 22,9.9 22,22 0,12.1 -9.9,22 -22,22 z m 133.4,69.4 H 63.999997 c -12.1,0 -22,-9.9 -22,-22 0,-12.1 9.9,-22 22,-22 H 373.1 c 12.1,0 22,9.9 22,22 0,12.1 -9.9,22 -22,22 z"
fill="#fbfaee"
id="path3" />
<path
d="M 811.5,631.20001 H 342.6 c -46.3,0 -83.9,-37.6 -83.9,-83.9 v -307 c 0,-46.3 37.6,-83.9 83.9,-83.9 h 468.9 c 46.3,0 83.9,37.6 83.9,83.9 v 306.9 c 0,46.4 -37.5,84 -83.9,84 z"
fill="#f5db6f"
id="path4" />
<path
d="M 724,410.80001 H 322.7 c -12.1,0 -22,-9.9 -22,-22 0,-12.1 9.9,-22 22,-22 H 724 c 12.1,0 22,9.9 22,22 0,12.1 -9.9,22 -22,22 z"
fill="#aeb8c4"
id="path5" />
<path
d="M 498.4,491.80001 H 322.7 c -12.1,0 -22,-9.9 -22,-22 0,-12.1 9.9,-22 22,-22 h 175.8 c 12.1,0 22,9.9 22,22 -0.1,12.1 -10,22 -22.1,22 z m 133.4,69.4 H 322.7 c -12.1,0 -22,-9.9 -22,-22 0,-12.1 9.9,-22 22,-22 h 309.1 c 12.1,0 22,9.9 22,22 0,12.1 -9.9,22 -22,22 z"
fill="#fbfaee"
id="path6" />
<path
d="M 446.1,323.90001 H 337.5 c -20.3,0 -36.8,-16.5 -36.8,-36.8 v -50.8 c 0,-20.3 16.5,-36.8 36.8,-36.8 h 108.6 c 20.3,0 36.8,16.5 36.8,36.8 v 50.8 c 0,20.3 -16.5,36.8 -36.8,36.8 z"
fill="#f3c262"
id="path7" />
<path
d="m 482.9,241.70001 h -34.3 v -42.2 h -33.9 v 124.4 h 33.9 v -47.7 h 34.3 z m -144.6,-42.2 v 42.2 h -37.6 v 34.5 h 37.6 v 47.7 h 33.9 v -124.4 z"
fill="#f7a04d"
id="path8" />
<path
d="m 895.4,381.40001 v -93.8 c -80.6,-0.3 -148.2,-56.4 -166.1,-131.6 h -95.5 c 19.2,127.2 129.2,225.1 261.6,225.4 z"
fill="#f7f9dd"
id="path9" />
<text
xml:space="preserve"
style="font-size:37.5466px;font-family:Azonix;-inkscape-font-specification:'Azonix, Normal';text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;shape-subtract:url(#path11);display:inline;fill:#ffffff;stroke:#ffffff;stroke-width:0.340312;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:0.68063, 0.340312;paint-order:stroke fill markers"
id="text1"
y="73.161377"
x="57.029587"><tspan
sodipodi:role="line"
id="tspan1"
style="display:inline;fill:#ffffff;stroke-width:0.340314"
x="57.029587"
y="73.161377">BASTIONGUARD</tspan></text>
<text
xml:space="preserve"
style="font-size:37.5466px;font-family:Azonix;-inkscape-font-specification:'Azonix, Normal';text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;shape-subtract:url(#path11);display:inline;fill:#000000;stroke:#ffffff;stroke-width:0.340312;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:0.68063, 0.340312;paint-order:stroke fill markers"
id="text1-6"
y="401.70981"
x="314.59656"><tspan
sodipodi:role="line"
id="tspan1-1"
style="display:inline;fill:#000000;stroke-width:0.340314"
x="314.59656"
y="401.70981">secure payments</tspan></text>
<text
xml:space="preserve"
style="font-size:17.0667px;font-family:Azonix;-inkscape-font-specification:'Azonix, Normal';text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;fill:#ffffff;stroke:#ffffff;stroke-width:0.340312;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:0.680632, 0.340312;paint-order:stroke fill markers"
x="381.35254"
y="48.824371"
id="text2"><tspan
sodipodi:role="line"
id="tspan2"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.0667px;font-family:sans-serif;-inkscape-font-specification:sans-serif;fill:#ffffff;stroke-width:0.340312"
x="381.35254"
y="48.824371">TM</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View file

@ -1,4 +1,5 @@
[Unit]
StartLimitIntervalSec=0
Description=BastionGuard CEF backend proxy (sandboxed, per-user)
After=graphical-session.target
Wants=graphical-session.target
@ -6,8 +7,8 @@ Wants=graphical-session.target
[Service]
Type=simple
ExecStart=/usr/bin/bastionguard-cef --listen 127.0.0.1 --port 3130
Restart=on-failure
RestartSec=1
Restart=always
RestartSec=3s
TimeoutStopSec=5s
KillSignal=SIGTERM
KillMode=control-group

View file

@ -1,4 +1,5 @@
[Unit]
StartLimitIntervalSec=0
Description=BastionGuard Mail Proxy
After=network-online.target
Wants=network-online.target
@ -6,8 +7,8 @@ Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/BastionGuard-mailproxy
Restart=on-failure
RestartSec=2
Restart=always
RestartSec=3s
TimeoutStopSec=5s
KillSignal=SIGTERM
Environment=HOME=%h

View file

@ -1,4 +1,5 @@
[Unit]
StartLimitIntervalSec=0
Description=BastionGuard PAC daemon (per-user)
After=network.target
@ -11,8 +12,8 @@ ExecStart=/usr/bin/bastionguard-pacd \
--trigger-cmd "systemctl --user start BastionGuard-cef.service" \
--backend-wait-ms 4000
Restart=on-failure
RestartSec=1
Restart=always
RestartSec=3s
TimeoutStopSec=5s
KillSignal=SIGTERM
KillMode=control-group

View file

@ -1,11 +1,12 @@
[Unit]
StartLimitIntervalSec=0
Description=BastionGuard Privacy Daemon
After=graphical-session.target
[Service]
ExecStart=/usr/bin/BastionGuard-privacyd
Restart=on-failure
RestartSec=3
Restart=always
RestartSec=3s
# 🔧 Ambiente grafico corretto
Environment=DISPLAY=:0

View file

@ -1,19 +1,20 @@
[Unit]
Description=BastionGuard Ransomware Alert (GUI)
After=graphical-session.target
Requires=graphical-session.target
PartOf=graphical-session.target
[Service]
Type=exec
Type=simple
ExecStart=/usr/bin/BastionGuard-ransomware-alert
# Programma che mostra la finestra di alert
ExecStart=/usr/bin/BastionGuard-ransomware-alert "%i"
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=%t/bus
Environment=XDG_RUNTIME_DIR=%t
Environment=GDK_BACKEND=wayland,x11
# Assicura che punti al bus grafico reale
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%U/bus
Restart=on-failure
RestartSec=3
# Sandbox leggera
NoNewPrivileges=yes
[Install]
WantedBy=default.target
WantedBy=graphical-session.target

View file

@ -1,4 +1,5 @@
[Unit]
StartLimitIntervalSec=0
Description=BastionGuard Realtime Ransomware Alert GUI
Documentation=https://github.com/BastionGuard
After=graphical-session.target
@ -31,8 +32,8 @@ ProtectKernelTunables=no
ProtectKernelModules=no
ProtectKernelLogs=no
Restart=on-failure
RestartSec=2
Restart=always
RestartSec=3s
[Install]
WantedBy=default.target

View file

@ -1,4 +1,5 @@
[Unit]
StartLimitIntervalSec=0
Description=BastionGuard Anti-Ransomware Scanner Daemon
After=graphical-session.target
@ -19,8 +20,8 @@ StandardOutput=journal
StandardError=journal
SyslogIdentifier=BastionGuard-antiransomware
Restart=on-failure
RestartSec=5s
Restart=always
RestartSec=3s
TimeoutStopSec=2s
KillSignal=SIGKILL
KillMode=control-group

View file

@ -0,0 +1,17 @@
[Unit]
Description=BastionGuard restart guard for user services on suspend/resume and session lock
After=graphical-session.target
Wants=graphical-session.target
PartOf=graphical-session.target
StartLimitIntervalSec=0
[Service]
Type=simple
ExecStart=/usr/share/BastionGuard/data/scripts/BastionGuard-user-session-watch.sh
Restart=always
RestartSec=3s
Environment=XDG_RUNTIME_DIR=%t
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=%t/bus
[Install]
WantedBy=default.target

View file

@ -1,4 +1,5 @@
[Unit]
StartLimitIntervalSec=0
Description=BastionGuard user agent (mostra notifiche / DBus agent)
After=graphical-session.target
@ -6,7 +7,8 @@ After=graphical-session.target
Type=simple
# Questo eseguibile deve essere l'agent che mostra finestre/notifiche in sessione utente
ExecStart=/usr/bin/BastionGuard-ransomware-alert
Restart=on-failure
Restart=always
RestartSec=3s
# Assicura che il processo abbia accesso all'ambiente dell'utente e al bus di sessione
Environment=XDG_RUNTIME_DIR=/run/user/%U

View file

@ -0,0 +1,16 @@
# /etc/sudoers.d/bastionguard-bank
#
# Permette a tutti gli utenti del gruppo "sudo" di eseguire bank-helper
# come root senza password e senza TTY, così l'aggiornamento della lista
# banche avviene in modo completamente silenzioso.
#
# INSTALLAZIONE:
# sudo install -m 440 bastionguard-bank /etc/sudoers.d/bastionguard-bank
# sudo visudo -c # verifica sintassi
# Limita PATH e azzera l'environment per questa regola specifica.
Defaults!/usr/bin/bank-helper env_reset, \
secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Regola principale: solo bank-helper, nessun'altra escalation.
%sudo ALL=(root) NOPASSWD: /usr/bin/bank-helper

View file

@ -0,0 +1,4 @@
# BastionGuard privacy helper
%SUDO ALL=(root) NOPASSWD: /usr/bin/bastionguard-privhelper block
%SUDO ALL=(root) NOPASSWD: /usr/bin/bastionguard-privhelper unblock

View file

@ -0,0 +1,2 @@
# BastionGuard — aggiornamento phishing blacklist senza password
ALL ALL=(root) NOPASSWD: /usr/share/BastionGuard/data/scripts/BastionGuard-phishing-updater.sh

View file

@ -1,2 +1,2 @@
version=1.1
build=20260310
version=2.0
build=20260411

View file

@ -0,0 +1,172 @@
/*
* BastionGuard™ — AUR Supply-Chain Detection
* Copyright (C) 2025–2026 Calogero Scarnà
*
* Rileva PKGBUILD e file .install compromessi.
* Pensato per il vettore della campagna "atomic-lockfile / Atomic Arch"
* (giugno 2026) ma generalizzato per intercettare compromissioni future.
*
* NOTA: queste regole girano su FILE DI TESTO (PKGBUILD, *.install, package.json),
* NON su ELF. Per questo il gate e' "uint32(0) != 0x7f454c46": vogliamo il
* VETTORE, non il payload. Il payload ELF lo coprono le tue regole cookie-stealer.
*
* Licenza: GPLv3. "BastionGuard" e' un marchio e non e' coperto dalla GPL.
*/
/* -------------------------------------------------------------------------
* 1) IOC SPECIFICI DELLA CAMPAGNA — confidenza massima
* ------------------------------------------------------------------------- */
rule AUR_Atomic_Lockfile_Campaign_IOC
{
meta:
description = "AUR: IOC campagna atomic-lockfile / Atomic Arch (giugno 2026)"
severity = "critical"
score = 95
response = "quarantine"
author = "BastionGuard"
reference = "PKGBUILD -> npm atomic-lockfile -> preinstall -> ELF src/hooks/deps"
date = "2026-06"
strings:
$ioc1 = "atomic-lockfile" ascii nocase
$ioc2 = "src/hooks/deps" ascii nocase
// marker di contesto AUR per ridurre i FP su testi che ne parlano soltanto
$ctx1 = "pkgname=" ascii
$ctx2 = "pkgver=" ascii
$ctx3 = /\bpackage\s*\(\s*\)/
$ctx4 = /\bprepare\s*\(\s*\)/
$ctx5 = /\bpost_install\s*\(\s*\)/
$ctx6 = "\"preinstall\"" ascii // package.json
condition:
uint32(0) != 0x7f454c46 and
filesize < 1MB and
(
$ioc1 // "atomic-lockfile" e' gia' distintivo
or ($ioc2 and any of ($ctx*)) // il path da solo e' piu' generico
)
}
/* -------------------------------------------------------------------------
* 2) PACKAGE MANAGER JS IN PKGBUILD/.install — vettore principale
* npm/bun/npx/pnpm/yarn che entrano dove non dovrebbero
* ------------------------------------------------------------------------- */
rule AUR_PKGBUILD_JS_PackageManager_Vector
{
meta:
description = "AUR: npm/bun/npx/pnpm/yarn in PKGBUILD o .install (vettore tipo atomic-lockfile)"
severity = "high"
score = 80
response = "quarantine_or_confirm"
author = "BastionGuard"
fix_notes = "npm in build()/package() di un progetto Node e' legittimo: per questo NON basta npm. Richiediamo npm DENTRO una scriptlet .install (gira come root) OPPURE accanto a lifecycle preinstall/postinstall."
strings:
$pm1 = "npm install" ascii
$pm2 = "npm ci" ascii
$pm3 = "npx " ascii
$pm4 = "bun install" ascii
$pm5 = "bunx" ascii
$pm6 = "pnpm " ascii
$pm7 = /yarn\s+(add|install)/
// scriptlet .install -> eseguite come root da pacman
$inst1 = /\bpost_install\s*\(\s*\)/
$inst2 = /\bpost_upgrade\s*\(\s*\)/
$inst3 = /\bpre_install\s*\(\s*\)/
$inst4 = /\bpre_upgrade\s*\(\s*\)/
// lifecycle npm sospetti in PKGBUILD/package.json
$life1 = "preinstall" ascii
$life2 = "postinstall" ascii
condition:
uint32(0) != 0x7f454c46 and
filesize < 1MB and
1 of ($pm*) and
(1 of ($inst*) or 1 of ($life*))
}
/* -------------------------------------------------------------------------
* 3) REMOTE EXEC — download pipato verso shell / eval / base64 decode
* Il classico curl|sh nascosto in build()/prepare()/scriptlet
* ------------------------------------------------------------------------- */
rule AUR_PKGBUILD_RemoteExec_Pipe_Shell
{
meta:
description = "AUR: download remoto pipato a shell, o decode/eval (RCE in fase di build/install)"
severity = "critical"
score = 90
response = "quarantine"
author = "BastionGuard"
fix_notes = "I sorgenti legittimi si scaricano via array source=() verificato da sha256sums. curl|sh inline dentro le funzioni e' il segnale: questo NON matcha source=()."
strings:
// contesto: deve essere un PKGBUILD o una .install
$ctx1 = "pkgname=" ascii
$ctx2 = /\bbuild\s*\(\s*\)/
$ctx3 = /\bprepare\s*\(\s*\)/
$ctx4 = /\bpackage\s*\(\s*\)/
$ctx5 = /\bpost_install\s*\(\s*\)/
$ctx6 = /\bpost_upgrade\s*\(\s*\)/
// download -> shell
$pipe1 = /curl[^\n]{0,300}\|\s*(ba)?sh\b/
$pipe2 = /wget[^\n]{0,300}\|\s*(ba)?sh\b/
$pipe3 = /\$\(\s*(curl|wget)[^\n)]{0,200}\)\s*\|\s*(ba)?sh/
// offuscamento -> shell
$dec1 = /base64\s+(-d|--decode)[^\n]{0,120}\|\s*(ba)?sh/
$dec2 = /eval\s+["'`$]?\(?\s*(curl|wget|base64)/
$dec3 = /(curl|wget)[^\n]{0,200}\|\s*base64\s+(-d|--decode)/
condition:
uint32(0) != 0x7f454c46 and
filesize < 1MB and
any of ($ctx*) and
any of ($pipe*, $dec*)
}
/* -------------------------------------------------------------------------
* 4) .install SCRIPTLET — rete o persistenza in contesto root
* Le scriptlet .install girano come root: rete/persistenza qui = quasi sempre malevolo
* ------------------------------------------------------------------------- */
rule AUR_Install_Scriptlet_Network_Or_Persistence
{
meta:
description = "AUR .install: scriptlet root con accesso rete o meccanismi di persistenza"
severity = "high"
score = 78
response = "quarantine_or_confirm"
author = "BastionGuard"
fix_notes = "'systemctl enable' e' sconsigliato ma talvolta usato da pacchetti aggressivi: tenuto come segnale debole. I segnali forti sono rete + autostart/cron/ld.so.preload/bashrc."
strings:
$sl1 = /\bpost_install\s*\(\s*\)/
$sl2 = /\bpost_upgrade\s*\(\s*\)/
$sl3 = /\bpre_install\s*\(\s*\)/
$sl4 = /\bpre_upgrade\s*\(\s*\)/
// rete (rarissima e sospetta in una scriptlet)
$net1 = /\bcurl\s/
$net2 = /\bwget\s/
$net3 = /\bnc\s+-/
$net4 = "/dev/tcp/" ascii
// persistenza
$per1 = "crontab" ascii
$per2 = "/etc/systemd/system/" ascii
$per3 = "/etc/profile.d/" ascii
$per4 = ".config/autostart" ascii
$per5 = "ld.so.preload" ascii
$per6 = /(>>?|tee)[^\n]{0,40}\.bashrc/
$per7 = "systemctl enable" ascii
condition:
uint32(0) != 0x7f454c46 and
filesize < 1MB and
1 of ($sl*) and
(1 of ($net*) or 1 of ($per*))
}

View file

@ -4,33 +4,30 @@ rule LINUX_POSSIBLE_RAINBOW_TABLE_ARCHIVE
author = "defensive"
description = "Linux: archive/container likely related to rainbow tables (heuristic)"
severity = "medium"
fix_notes = "FP fix: 'reduction' sostituito con 'reduction function' (piu' specifico); LM e NTLM ora fullword per evitare match in parole come 'algorithm'"
strings:
// keywords
$kw1 = "rainbow table" nocase ascii
$kw2 = "rainbowtable" nocase ascii
$kw3 = "precomputed" nocase ascii
$kw4 = "chain length" nocase ascii
$kw5 = "chain count" nocase ascii
$kw6 = "reduction" nocase ascii
$kw6 = "reduction function" nocase ascii
$kw7 = "rtgen" nocase ascii
$kw8 = "rcrack" nocase ascii
$kw9 = "ophcrack" nocase ascii
// algorithms
$h1 = "LM" ascii
$h2 = "NTLM" ascii
$h1 = "LM" fullword ascii
$h2 = "NTLM" fullword ascii
$h3 = "MD5" ascii
$h4 = "SHA1" ascii
$h5 = "SHA-1" ascii
$h6 = "SHA256" ascii
$h7 = "SHA-256" ascii
// magic bytes for common containers
$zip = { 50 4B 03 04 }
$rar = { 52 61 72 21 1A 07 }
$7z = { 37 7A BC AF 27 1C }
// tar spesso non ha magic affidabile: si intercetta meglio via pipeline (tar -tf) e scan contenuti
condition:
(any of ($zip,$rar,$7z)) and
@ -38,4 +35,3 @@ rule LINUX_POSSIBLE_RAINBOW_TABLE_ARCHIVE
(1 of ($h*)) and
filesize > 1MB
}

View file

@ -5,6 +5,7 @@ rule LINUX_Cookie_Staging_And_Packaging_High
severity = "high"
score = 85
response = "quarantine_or_confirm"
fix_notes = "FP fix: aggiunto check ELF + fullword su keywords packaging"
strings:
$st1 = "/tmp/" ascii
@ -16,12 +17,12 @@ rule LINUX_Cookie_Staging_And_Packaging_High
$cookie2 = "/Default/Cookies" ascii
$cookie3 = "Login Data" ascii
$pack1 = "zip" ascii
$pack2 = "tar" ascii
$pack3 = "gzip" ascii
$pack4 = "7z" ascii
$pack1 = "zip" fullword ascii
$pack2 = "tar" fullword ascii
$pack3 = "gzip" fullword ascii
$pack4 = "7z" fullword ascii
condition:
uint32(0) == 0x7f454c46 and
(1 of ($st*)) and (1 of ($cookie*)) and (1 of ($pack*))
}

View file

@ -3,6 +3,7 @@ rule LINUX_Browser_Cookie_Theft_Chromium_Paths
meta:
description = "Linux: riferimenti a path cookie Chromium-based (Chrome/Chromium/Brave/Edge)"
severity = "high"
fix_notes = "FP fix: aggiunto check ELF - senza questo qualsiasi file testuale con questi path triggera la regola"
strings:
$p1 = "/.config/google-chrome/Default/Cookies" ascii
@ -14,6 +15,6 @@ rule LINUX_Browser_Cookie_Theft_Chromium_Paths
$p7 = "/Profile 2/Cookies" ascii
condition:
uint32(0) == 0x7f454c46 and
any of them
}

View file

@ -3,6 +3,7 @@ rule LINUX_Browser_Cookie_Theft_Firefox_Paths
meta:
description = "Linux: riferimenti a Firefox cookies.sqlite e profili"
severity = "high"
fix_notes = "FP fix: aggiunto check ELF - cookies.sqlite e profiles.ini sono presenti in backup/script legittimi"
strings:
$f1 = "/.mozilla/firefox/" ascii
@ -10,5 +11,6 @@ rule LINUX_Browser_Cookie_Theft_Firefox_Paths
$f3 = "profiles.ini" ascii
condition:
uint32(0) == 0x7f454c46 and
$f1 and ($f2 or $f3)
}

View file

@ -5,6 +5,7 @@ rule LINUX_Browser_DataCollector_Medium
severity = "medium"
score = 55
response = "alert"
fix_notes = "FP fix: aggiunto check ELF - stringhe come 'Cookies','History','Web Data' sono troppo generiche senza vincolo tipo file"
strings:
$a1 = "Cookies" ascii
@ -19,6 +20,6 @@ rule LINUX_Browser_DataCollector_Medium
$b3 = "/.mozilla/firefox/" ascii
condition:
uint32(0) == 0x7f454c46 and
3 of ($a*) and 1 of ($b*)
}

View file

@ -4,15 +4,15 @@ rule Linux_Ransomware_Core
description = "Ransomware ELF noti - regola stabile"
author = "BastionGuard"
confidence = "high"
fix_notes = "FP fix: aggiunto parentesi nella condizione - senza di esse il check ELF e filesize NON si applicavano a $note, causando match su file di testo normali"
strings:
$s1 = { 48 8D 3D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 89 C3 } // pattern comune in più famiglie
$s2 = { 55 48 89 E5 48 83 EC 20 48 89 7D F8 31 C0 } // prologue usato in crypto-ransomware
$s1 = { 48 8D 3D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 89 C3 }
$s2 = { 55 48 89 E5 48 83 EC 20 48 89 7D F8 31 C0 }
$note = "Your files have been encrypted" wide ascii
condition:
uint32(0) == 0x7f454c46 and // SOLO ELF
filesize < 20MB and // evita FP su binari enormi
any of ($s*) or $note
uint32(0) == 0x7f454c46 and
filesize < 20MB and
(any of ($s*) or $note)
}

View file

@ -3,6 +3,7 @@ rule Linux_Ransomware_Extensions_Strict
meta:
description = "Estensioni ransomware embedded, solo per ELF"
author = "BastionGuard"
fix_notes = "FP fix: alzata soglia a 2 of 3 - .enc e .crypt sono usate da tool di cifratura legittimi (OpenSSL, KDE Wallet)"
strings:
$e1 = ".locked" ascii
@ -11,6 +12,5 @@ rule Linux_Ransomware_Extensions_Strict
condition:
uint32(0) == 0x7f454c46 and
any of ($e*)
2 of ($e*)
}

View file

@ -3,6 +3,7 @@ rule Linux_Ransomware_Packer
meta:
description = "Packer tipici usati dai ransomware Linux"
author = "BastionGuard"
fix_notes = "FP fix: i pattern $crypt1/$crypt2 sono sequenze x86-64 generiche - limitati a filesize < 5MB per ridurre FP su binari di sistema"
strings:
$upx0 = "UPX!" ascii
@ -11,5 +12,5 @@ rule Linux_Ransomware_Packer
condition:
uint32(0) == 0x7f454c46 and
1 of ($upx0,$crypt1,$crypt2)
($upx0 or (1 of ($crypt*) and filesize < 5MB))
}

View file

@ -4,18 +4,18 @@ rule LINUX_ELF_TOOL_OPHCRACK_RELATED
author = "defensive"
description = "Linux ELF: Ophcrack-related binaries by strings"
severity = "high"
fix_notes = "BUG FIX CRITICO: magic byte era 0x464C457F (big-endian errato) - su x86/x86-64 uint32(0) legge little-endian, il valore corretto e' 0x7f454c46. La regola originale non matchava alcun ELF reale."
strings:
$k1 = "ophcrack" nocase ascii
$k2 = "load tables" nocase ascii
$k3 = "tables" nocase ascii
$k4 = "LM" ascii
$k5 = "NTLM" ascii
$k4 = "LM" fullword ascii
$k5 = "NTLM" fullword ascii
$k6 = "SAM" ascii
condition:
uint32(0) == 0x464C457F and
uint32(0) == 0x7f454c46 and
$k1 and 2 of ($k2,$k3,$k4,$k5,$k6) and
filesize < 200MB
}

View file

@ -4,15 +4,14 @@ rule LINUX_ELF_TOOL_RAINBOWCRACK_FAMILY
author = "defensive"
description = "Linux ELF: RainbowCrack family tools by CLI strings"
severity = "high"
fix_notes = "BUG FIX CRITICO: magic byte era 0x464C457F (big-endian errato) - su x86/x86-64 uint32(0) legge little-endian, il valore corretto e' 0x7f454c46. La regola originale non matchava alcun ELF reale."
strings:
// tool names / banners
$t1 = "rtgen" nocase ascii
$t2 = "rtsort" nocase ascii
$t3 = "rcrack" nocase ascii
$t4 = "rainbowcrack" nocase ascii
// typical parameters/terms
$p1 = "chain length" nocase ascii
$p2 = "chain count" nocase ascii
$p3 = "table index" nocase ascii
@ -23,19 +22,16 @@ rule LINUX_ELF_TOOL_RAINBOWCRACK_FAMILY
$p8 = "--help" ascii
$p9 = "-h" ascii
// common targets
$h1 = "LM" ascii
$h2 = "NTLM" ascii
$h3 = "MD5" ascii
$h4 = "SHA1" ascii
$h5 = "SHA-1" ascii
$h1 = "LM" fullword ascii
$h2 = "NTLM" fullword ascii
$h3 = "MD5" fullword ascii
$h4 = "SHA1" fullword ascii
$h5 = "SHA-1" fullword ascii
condition:
uint32(0) == 0x464C457F and
uint32(0) == 0x7f454c46 and
(1 of ($t*)) and
(2 of ($p1,$p2,$p3,$p4,$p5,$p6,$p7,$p8,$p9)) and
(1 of ($h*)) and
filesize < 50MB
}

View file

@ -4,6 +4,7 @@ rule LINUX_MEM_RAINBOW_TOOL_RUNTIME
author = "defensive"
description = "Linux memory: runtime strings indicating rainbow table tool execution"
severity = "high"
fix_notes = "FP fix: rimossa $e1='.rt' (troppo breve e generica), condizione ora richiede .rtc o .rti che sono estensioni specifiche dei file rainbow table"
strings:
$s1 = "rtgen" nocase ascii
@ -22,7 +23,6 @@ rule LINUX_MEM_RAINBOW_TOOL_RUNTIME
$h4 = "SHA1" ascii
$h5 = "SHA-1" ascii
$e1 = ".rt" ascii
$e2 = ".rtc" ascii
$e3 = ".rti" ascii
@ -30,6 +30,5 @@ rule LINUX_MEM_RAINBOW_TOOL_RUNTIME
(1 of ($s1,$s2,$s3,$s4)) and
(2 of ($s5,$s6,$s7,$s8,$s9)) and
(1 of ($h*)) and
(1 of ($e*))
(1 of ($e2,$e3))
}

0
debian/bastionguard-donate.postinst vendored Normal file
View file

6
debian/bastionguard.dirs vendored Normal file
View file

@ -0,0 +1,6 @@
var/lib/bastionguard-webui
var/lib/bastionguard-webui/cache
var/lib/bastionguard-webui/quarantine
var/lib/bastionguard-webui/sessions
var/lib/bastionguard-webui/tmp
var/log/bastionguard-webui

View file

@ -9,3 +9,16 @@ usr/share/dbus-1/services/*.service usr/share/dbus-1/services/
usr/lib/systemd/system/* usr/lib/systemd/system/
usr/lib/systemd/user/* usr/lib/systemd/user/
usr/libexec/bastionguard/archive_worker usr/libexec/bastionguard/
etc/sudoers.d/* etc/sudoers.d/
usr/share/bastionguard-backup/* usr/share/bastionguard-backup/
usr/share/bastionguard-sc/* usr/share/bastionguard-sc/
usr/share/bastionguard-recovery-data/* usr/share/bastionguard-recovery-data/
usr/share/plymouth/themes/bastionguard/* usr/share/plymouth/themes/bastionguard/
etc/bastionguard-secure-connectiond/* etc/bastionguard-secure-connectiond/
usr/share/pixmaps/* usr/share/pixmaps/
usr/share/locale/* usr/share/locale/
usr/share/icons/hicolor/*/apps/*
etc/bastionguard-backup/* etc/bastionguard-backup/
usr/lib/bastionguard-sc/* usr/lib/bastionguard-sc/
usr/share/metainfo/* usr/share/metainfo/
usr/share/man/* usr/share/man/

View file

@ -98,7 +98,19 @@ set(CMAKE_AUTORCC OFF)
find_package(PkgConfig REQUIRED)
find_package(Gettext REQUIRED)
# ======================
# libsystemd / sd-bus
# ======================
pkg_check_modules(SYSTEMD REQUIRED libsystemd)
if (SYSTEMD_FOUND)
message(STATUS "✔ libsystemd trovato: ${SYSTEMD_VERSION}")
include_directories(${SYSTEMD_INCLUDE_DIRS})
link_directories(${SYSTEMD_LIBRARY_DIRS})
add_definitions(${SYSTEMD_CFLAGS_OTHER})
else()
message(FATAL_ERROR "❌ libsystemd non trovato. Installa libsystemd-dev")
endif()
# ==============================
# Controllo NGINX
# ==============================
@ -412,6 +424,36 @@ target_link_libraries(identity_leak
nlohmann_json::nlohmann_json
)
# ======================
# Password Manager Module
# ======================
set(PASSWORD_MANAGER_SOURCES
src/password_manager/PasswordEntry.cpp
src/password_manager/PasswordVault.cpp
src/password_manager/PasswordGenerator.cpp
src/password_manager/PasswordDialogs.cpp
src/password_manager/PasswordSearchRow.cpp
src/password_manager/PasswordManagerPage.cpp
src/password_manager/PasswordImporter.cpp
src/password_manager/PasswordImportDialog.cpp
src/password_manager/PasswordVaultView.cpp
)
add_library(password_manager STATIC ${PASSWORD_MANAGER_SOURCES})
target_include_directories(password_manager PUBLIC
src
src/password_manager
)
target_link_libraries(password_manager
PUBLIC
${GTKMM_LIBRARIES}
${GIOMM_LIBRARIES}
${SIGC_LIBRARIES}
${LIBSECRET_LIBRARIES}
nlohmann_json::nlohmann_json
)
# ======================
# RE2 (opzionale, per regex sicure e veloci)
@ -500,6 +542,11 @@ set(BastionGuard_SOURCES
src/usb/LiveScanDialog.cpp
src/phishing_search/PhishingPage.cpp
src/phishing_search/PhishingCheckCard.cpp
src/vpn/VpnPage.cpp
src/vpn/WireguardBackend.cpp
src/password_manager/PasswordManagerPage.cpp
src/backup/BackupPage.cpp
src/Utils.cpp
)
# === Eseguibile principale ===
@ -511,8 +558,8 @@ target_include_directories(BastionGuard
)
target_compile_definitions(BastionGuard PRIVATE
BASTIONGUARD_VERSION="1.1"
BASTIONGUARD_BUILD=20260310
BASTIONGUARD_VERSION="2.0"
BASTIONGUARD_BUILD=20260411
)
target_link_libraries(BastionGuard
@ -528,11 +575,13 @@ target_link_libraries(BastionGuard
phishing_common
firewall
identity_leak
password_manager
CURL::libcurl
OpenSSL::SSL
OpenSSL::Crypto
${SYSTEMD_LIBRARIES}
)
target_link_options(BastionGuard PRIVATE -lsystemd)
bg_set_rpath(BastionGuard)
bg_link_systemd(BastionGuard)
# ============================================================
@ -741,6 +790,7 @@ set(RANSW_ALERT_SOURCES
src/AntiRansomEngine.cpp
src/AntiPhishingEngine.cpp
src/Quarantine.cpp
src/Utils.cpp
)
add_executable(BastionGuard-ransomware-alert ${RANSW_ALERT_SOURCES})
@ -777,6 +827,7 @@ set(RANSW_REALTIME_ALERT_SOURCES
src/AntiRansomEngine.cpp
src/AntiPhishingEngine.cpp
src/Quarantine.cpp
src/Utils.cpp
)
add_executable(BastionGuard-ransomware-realtime-alert ${RANSW_REALTIME_ALERT_SOURCES})
@ -966,6 +1017,7 @@ set(WIZARD_SOURCES
src/wizard/wizard_setup.cpp
src/wizard/main.cpp
src/wizard/StyleProvider.cpp
src/Utils.cpp
)
add_executable(BastionGuard-wizard ${WIZARD_SOURCES})
@ -1301,6 +1353,8 @@ target_link_libraries(bastionguard-cef
PRIVATE
${BG_BOOST_HEADERS}
Threads::Threads
OpenSSL::SSL
OpenSSL::Crypto
${GTKMM_LIBRARIES}
${GIOMM_LIBRARIES}
${SIGC_LIBRARIES}
@ -1395,6 +1449,7 @@ install(TARGETS BastionGuard-secure RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# ---- GUI selector ----
add_executable(BastionGuard-secure-gui
src/payment_secure/BastionGuard-secure-main.cpp
src/payment_secure/dns_secure.cpp
src/StyleProvider.cpp
)
@ -1470,6 +1525,497 @@ install(FILES
)
# ============================================================
# BastionGuard WebUI
# ============================================================
set(BG_WEBUI_SOURCE_DIR "${CMAKE_SOURCE_DIR}/webui")
set(BG_WEBUI_BUILD_DIR "${CMAKE_BINARY_DIR}/webui")
set(BG_WEBUI_STAMP "${BG_WEBUI_BUILD_DIR}/.webui-staged")
if(EXISTS "${BG_WEBUI_SOURCE_DIR}/index.php")
add_custom_command(
OUTPUT "${BG_WEBUI_STAMP}"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${BG_WEBUI_SOURCE_DIR}"
"${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E touch "${BG_WEBUI_STAMP}"
DEPENDS "${BG_WEBUI_SOURCE_DIR}/index.php"
COMMENT "Staging BastionGuard WebUI into the build directory"
VERBATIM
)
add_custom_target(BastionGuard-webui ALL
DEPENDS "${BG_WEBUI_STAMP}"
)
install(DIRECTORY "${BG_WEBUI_BUILD_DIR}/"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/webui"
USE_SOURCE_PERMISSIONS
COMPONENT webui
PATTERN ".git" EXCLUDE
PATTERN "*.bak" EXCLUDE
PATTERN "*.tmp" EXCLUDE
PATTERN ".webui-staged" EXCLUDE
)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/data/vhosts/webui/"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data/vhosts/webui"
USE_SOURCE_PERMISSIONS
COMPONENT webui
OPTIONAL
)
install(CODE "
message(STATUS \"[WebUI] Installed in: ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/webui\")
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/cache)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/quarantine)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/sessions)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/tmp)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/log/bastionguard-webui)
")
else()
message(WARNING "BastionGuard WebUI source not found at ${BG_WEBUI_SOURCE_DIR}; WebUI will not be installed.")
endif()
# ======================
# BastionGuard Backup (fork di Timeshift, build via Meson)
# ======================
option(ENABLE_BASTIONGUARD_BACKUP "Build bastionguard-backup (Timeshift fork)" ON)
if(ENABLE_BASTIONGUARD_BACKUP)
include(ExternalProject)
find_program(MESON_EXECUTABLE meson REQUIRED)
find_program(NINJA_EXECUTABLE ninja REQUIRED)
find_program(VALAC_EXECUTABLE valac REQUIRED)
find_program(PKG_CONFIG_EXECUTABLE pkg-config REQUIRED)
# Dipendenze runtime/build del fork
pkg_check_modules(BG_BACKUP_GTK3 REQUIRED gtk+-3.0)
pkg_check_modules(BG_BACKUP_GIO REQUIRED gio-2.0 gio-unix-2.0)
pkg_check_modules(BG_BACKUP_JSON REQUIRED json-glib-1.0)
pkg_check_modules(BG_BACKUP_VTE REQUIRED vte-2.91)
pkg_check_modules(BG_BACKUP_GEE REQUIRED gee-0.8)
set(BG_BACKUP_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-backup")
set(BG_BACKUP_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-backup-build")
set(BG_BACKUP_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-backup-install")
message(STATUS "[BG-Backup] Source dir : ${BG_BACKUP_SOURCE_DIR}")
message(STATUS "[BG-Backup] Build dir : ${BG_BACKUP_BINARY_DIR}")
message(STATUS "[BG-Backup] Stage dir : ${BG_BACKUP_INSTALL_DIR}")
message(STATUS "[BG-Backup] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_backup_ext
SOURCE_DIR "${BG_BACKUP_SOURCE_DIR}"
BINARY_DIR "${BG_BACKUP_BINARY_DIR}"
CONFIGURE_COMMAND
${MESON_EXECUTABLE} setup "${BG_BACKUP_BINARY_DIR}" "${BG_BACKUP_SOURCE_DIR}"
--prefix=/usr
--buildtype=release
--reconfigure
BUILD_COMMAND
${MESON_EXECUTABLE} compile -C "${BG_BACKUP_BINARY_DIR}"
INSTALL_COMMAND
${MESON_EXECUTABLE} install -C "${BG_BACKUP_BINARY_DIR}" --destdir "${BG_BACKUP_INSTALL_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-backup ALL
DEPENDS bastionguard_backup_ext
)
install(CODE "
set(BG_BACKUP_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-Backup] =====================================\")
message(STATUS \"[BG-Backup] Installazione bastionguard-backup\")
message(STATUS \"[BG-Backup] Stage dir Meson : ${BG_BACKUP_INSTALL_DIR}\")
message(STATUS \"[BG-Backup] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-Backup] DESTDIR : \${BG_BACKUP_DESTDIR}\")
message(STATUS \"[BG-Backup]\")
set(BG_BACKUP_STAGE_BIN \"${BG_BACKUP_INSTALL_DIR}/usr/bin\")
set(BG_BACKUP_STAGE_SHARE \"${BG_BACKUP_INSTALL_DIR}/usr/share\")
set(BG_BACKUP_STAGE_ETC \"${BG_BACKUP_INSTALL_DIR}/etc\")
set(BG_BACKUP_DEST_BIN \"\${BG_BACKUP_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_BACKUP_DEST_SHARE \"\${BG_BACKUP_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_BACKUP_DEST_ETC \"\${BG_BACKUP_DESTDIR}/etc\")
message(STATUS \"[BG-Backup] Copia binari : \${BG_BACKUP_STAGE_BIN} -> \${BG_BACKUP_DEST_BIN}\")
if(EXISTS \"\${BG_BACKUP_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_BIN}\"
\"\${BG_BACKUP_DEST_BIN}\"
RESULT_VARIABLE BG_BACKUP_BIN_RES
)
if(NOT BG_BACKUP_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando i binari in \${BG_BACKUP_DEST_BIN}\")
endif()
else()
message(WARNING \"[BG-Backup] Directory bin non trovata: \${BG_BACKUP_STAGE_BIN}\")
endif()
message(STATUS \"[BG-Backup] Copia share : \${BG_BACKUP_STAGE_SHARE} -> \${BG_BACKUP_DEST_SHARE}\")
if(EXISTS \"\${BG_BACKUP_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_SHARE}\"
\"\${BG_BACKUP_DEST_SHARE}\"
RESULT_VARIABLE BG_BACKUP_SHARE_RES
)
if(NOT BG_BACKUP_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando share in \${BG_BACKUP_DEST_SHARE}\")
endif()
else()
message(WARNING \"[BG-Backup] Directory share non trovata: \${BG_BACKUP_STAGE_SHARE}\")
endif()
message(STATUS \"[BG-Backup] Copia etc : \${BG_BACKUP_STAGE_ETC} -> \${BG_BACKUP_DEST_ETC}\")
if(EXISTS \"\${BG_BACKUP_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_ETC}\"
\"\${BG_BACKUP_DEST_ETC}\"
RESULT_VARIABLE BG_BACKUP_ETC_RES
)
if(NOT BG_BACKUP_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando etc in \${BG_BACKUP_DEST_ETC}\")
endif()
else()
message(STATUS \"[BG-Backup] Nessuna directory etc da installare\")
endif()
message(STATUS \"[BG-Backup] ✔ installazione completata\")
message(STATUS \"[BG-Backup] =====================================\")
")
endif()
# ======================
# BastionGuard Secure Connection (Meson + Go)
# ======================
option(ENABLE_BASTIONGUARD_SECURE_CONNECTION "Build bastionguard-secure-connection" ON)
if(ENABLE_BASTIONGUARD_SECURE_CONNECTION)
include(ExternalProject)
find_program(MESON_EXECUTABLE meson REQUIRED)
find_program(NINJA_EXECUTABLE ninja REQUIRED)
find_program(GO_EXECUTABLE go REQUIRED)
find_program(PROTOC_EXECUTABLE protoc REQUIRED)
find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin REQUIRED)
find_program(PKG_CONFIG_EXECUTABLE pkg-config REQUIRED)
set(BG_SC_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-secure-connection")
set(BG_SC_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-secure-connection-build")
set(BG_SC_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-secure-connection-install")
message(STATUS "[BG-SC] Source dir : ${BG_SC_SOURCE_DIR}")
message(STATUS "[BG-SC] Build dir : ${BG_SC_BINARY_DIR}")
message(STATUS "[BG-SC] Stage dir : ${BG_SC_INSTALL_DIR}")
message(STATUS "[BG-SC] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_secure_connection_ext
SOURCE_DIR "${BG_SC_SOURCE_DIR}"
BINARY_DIR "${BG_SC_BINARY_DIR}"
CONFIGURE_COMMAND
${MESON_EXECUTABLE} setup "${BG_SC_BINARY_DIR}" "${BG_SC_SOURCE_DIR}"
--prefix=/usr
--sysconfdir=/etc
--localedir=share/locale
--buildtype=release
--reconfigure
BUILD_COMMAND
${MESON_EXECUTABLE} compile -C "${BG_SC_BINARY_DIR}"
INSTALL_COMMAND
${MESON_EXECUTABLE} install -C "${BG_SC_BINARY_DIR}" --destdir "${BG_SC_INSTALL_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-secure-connection ALL
DEPENDS bastionguard_secure_connection_ext
)
install(CODE "
set(BG_SC_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-SC] =====================================\")
message(STATUS \"[BG-SC] Installazione bastionguard-secure-connection\")
message(STATUS \"[BG-SC] Stage dir Meson : ${BG_SC_INSTALL_DIR}\")
message(STATUS \"[BG-SC] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-SC] DESTDIR : \${BG_SC_DESTDIR}\")
set(BG_SC_STAGE_BIN \"${BG_SC_INSTALL_DIR}/usr/bin\")
set(BG_SC_STAGE_SHARE \"${BG_SC_INSTALL_DIR}/usr/share\")
set(BG_SC_STAGE_ETC \"${BG_SC_INSTALL_DIR}/etc\")
set(BG_SC_STAGE_LIB \"${BG_SC_INSTALL_DIR}/usr/lib\")
set(BG_SC_DEST_BIN \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_SC_DEST_SHARE \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_SC_DEST_ETC \"\${BG_SC_DESTDIR}/etc\")
set(BG_SC_DEST_LIB \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/lib\")
if(EXISTS \"\${BG_SC_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_BIN}\"
\"\${BG_SC_DEST_BIN}\"
RESULT_VARIABLE BG_SC_BIN_RES
)
if(NOT BG_SC_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando i binari\")
endif()
endif()
if(EXISTS \"\${BG_SC_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_SHARE}\"
\"\${BG_SC_DEST_SHARE}\"
RESULT_VARIABLE BG_SC_SHARE_RES
)
if(NOT BG_SC_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando share\")
endif()
endif()
if(EXISTS \"\${BG_SC_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_ETC}\"
\"\${BG_SC_DEST_ETC}\"
RESULT_VARIABLE BG_SC_ETC_RES
)
if(NOT BG_SC_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando etc\")
endif()
endif()
# ── Copia esplicita config daemon in /etc/bastionguard-secure-connectiond ──
# Meson installa i JSON con sysconfdir=/etc (assoluto), quindi nella stage
# finiscono sempre in <INSTALL_DIR>/etc/bastionguard-secure-connectiond/.
# Con DESTDIR finiscono dentro il pkgdir, senza DESTDIR in /etc di sistema.
set(BG_SC_CONF_SRC \"${BG_SC_INSTALL_DIR}/etc/bastionguard-secure-connectiond\")
set(BG_SC_CONF_DST \"\${BG_SC_DESTDIR}/etc/bastionguard-secure-connectiond\")
if(EXISTS \"\${BG_SC_CONF_SRC}\")
file(MAKE_DIRECTORY \"\${BG_SC_CONF_DST}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_CONF_SRC}\"
\"\${BG_SC_CONF_DST}\"
RESULT_VARIABLE BG_SC_CONF_RES
)
if(NOT BG_SC_CONF_RES EQUAL 0)
message(WARNING \"[BG-SC] Impossibile copiare la config (permessi?): \${BG_SC_CONF_DST}\")
else()
message(STATUS \"[BG-SC] ✔ Config daemon installata: \${BG_SC_CONF_DST}\")
endif()
else()
message(WARNING \"[BG-SC] Directory config non trovata nella stage: \${BG_SC_CONF_SRC}\")
endif()
# ── Copia esplicita autostart in /etc/xdg/autostart ──────────────────
set(BG_SC_AUTOSTART_SRC
\"${BG_SC_INSTALL_DIR}/etc/xdg/autostart/bastionguard-sc-autostart.desktop\")
set(BG_SC_AUTOSTART_DST \"\${BG_SC_DESTDIR}/etc/xdg/autostart/bastionguard-sc-autostart.desktop\")
if(EXISTS \"\${BG_SC_AUTOSTART_SRC}\")
file(MAKE_DIRECTORY \"\${BG_SC_DESTDIR}/etc/xdg/autostart\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy
\"\${BG_SC_AUTOSTART_SRC}\"
\"\${BG_SC_AUTOSTART_DST}\"
RESULT_VARIABLE BG_SC_AUTOSTART_RES
)
if(NOT BG_SC_AUTOSTART_RES EQUAL 0)
message(WARNING \"[BG-SC] Impossibile copiare l'autostart (permessi?): \${BG_SC_AUTOSTART_DST}\")
else()
message(STATUS \"[BG-SC] ✔ Autostart installato: \${BG_SC_AUTOSTART_DST}\")
endif()
else()
message(WARNING \"[BG-SC] File autostart non trovato nella stage: \${BG_SC_AUTOSTART_SRC}\")
endif()
if(EXISTS \"\${BG_SC_STAGE_LIB}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_LIB}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_LIB}\"
\"\${BG_SC_DEST_LIB}\"
RESULT_VARIABLE BG_SC_LIB_RES
)
if(NOT BG_SC_LIB_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando lib\")
endif()
endif()
message(STATUS \"[BG-SC] ✔ installazione completata\")
message(STATUS \"[BG-SC] =====================================\")
")
endif()
# ======================
# BastionGuard Recovery Data (CMake)
# ======================
option(ENABLE_BASTIONGUARD_RECOVERY_DATA "Build bastionguard-recovery-data" ON)
if(ENABLE_BASTIONGUARD_RECOVERY_DATA)
include(ExternalProject)
set(BG_RD_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-recovery-data")
set(BG_RD_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-recovery-data-build")
set(BG_RD_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-recovery-data-install")
message(STATUS "[BG-RD] Source dir : ${BG_RD_SOURCE_DIR}")
message(STATUS "[BG-RD] Build dir : ${BG_RD_BINARY_DIR}")
message(STATUS "[BG-RD] Stage dir : ${BG_RD_INSTALL_DIR}")
message(STATUS "[BG-RD] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_recovery_data_ext
SOURCE_DIR "${BG_RD_SOURCE_DIR}"
BINARY_DIR "${BG_RD_BINARY_DIR}"
CONFIGURE_COMMAND
"${CMAKE_COMMAND}" -S "${BG_RD_SOURCE_DIR}" -B "${BG_RD_BINARY_DIR}"
-DCMAKE_INSTALL_PREFIX=/usr
-DCMAKE_BUILD_TYPE=Release
BUILD_COMMAND
"${CMAKE_COMMAND}" --build "${BG_RD_BINARY_DIR}" --parallel
INSTALL_COMMAND
"${CMAKE_COMMAND}" -E env DESTDIR=${BG_RD_INSTALL_DIR}
"${CMAKE_COMMAND}" --install "${BG_RD_BINARY_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-recovery-data ALL
DEPENDS bastionguard_recovery_data_ext
)
install(CODE "
set(BG_RD_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-RD] =====================================\")
message(STATUS \"[BG-RD] Installazione bastionguard-recovery-data\")
message(STATUS \"[BG-RD] Stage dir CMake : ${BG_RD_INSTALL_DIR}\")
message(STATUS \"[BG-RD] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-RD] DESTDIR : \${BG_RD_DESTDIR}\")
set(BG_RD_STAGE_BIN \"${BG_RD_INSTALL_DIR}/usr/bin\")
set(BG_RD_STAGE_SHARE \"${BG_RD_INSTALL_DIR}/usr/share\")
set(BG_RD_STAGE_ETC \"${BG_RD_INSTALL_DIR}/etc\")
set(BG_RD_STAGE_LIB \"${BG_RD_INSTALL_DIR}/usr/lib\")
set(BG_RD_DEST_BIN \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_RD_DEST_SHARE \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_RD_DEST_ETC \"\${BG_RD_DESTDIR}/etc\")
set(BG_RD_DEST_LIB \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/lib\")
if(EXISTS \"\${BG_RD_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_BIN}\"
\"\${BG_RD_DEST_BIN}\"
RESULT_VARIABLE BG_RD_BIN_RES
)
if(NOT BG_RD_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando i binari\")
endif()
else()
message(WARNING \"[BG-RD] Directory bin non trovata: \${BG_RD_STAGE_BIN}\")
endif()
if(EXISTS \"\${BG_RD_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_SHARE}\"
\"\${BG_RD_DEST_SHARE}\"
RESULT_VARIABLE BG_RD_SHARE_RES
)
if(NOT BG_RD_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando share\")
endif()
else()
message(WARNING \"[BG-RD] Directory share non trovata: \${BG_RD_STAGE_SHARE}\")
endif()
if(EXISTS \"\${BG_RD_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_ETC}\"
\"\${BG_RD_DEST_ETC}\"
RESULT_VARIABLE BG_RD_ETC_RES
)
if(NOT BG_RD_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando etc\")
endif()
else()
message(STATUS \"[BG-RD] Nessuna directory etc da installare\")
endif()
if(EXISTS \"\${BG_RD_STAGE_LIB}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_LIB}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_LIB}\"
\"\${BG_RD_DEST_LIB}\"
RESULT_VARIABLE BG_RD_LIB_RES
)
if(NOT BG_RD_LIB_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando lib\")
endif()
endif()
message(STATUS \"[BG-RD] ✔ installazione completata\")
message(STATUS \"[BG-RD] =====================================\")
")
endif()
# ======================
# Traduzioni con gettext
# ======================
@ -1652,6 +2198,7 @@ install(FILES data/service/org.BastionGuard.RansomwareAlert.service
install(FILES actions/policy/org.BastionGuard.policy
FILES actions/policy/org.BastionGuard.ransomware.policy
FILES actions/policy/org.BastionGuard.USBD.policy
FILES actions/policy/eu.bastionguard.install-ca.policy
DESTINATION /usr/share/polkit-1/actions
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
@ -1659,7 +2206,7 @@ install(FILES actions/dbus/org.BastionGuard.USBD.conf
DESTINATION /usr/share/dbus-1/system.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# Install DBus activation service (system bus)
# Install DBus system service
install(
FILES actions/dbus/org.BastionGuard.USBD.service
DESTINATION /usr/share/dbus-1/system-services
@ -1673,11 +2220,37 @@ install(FILES actions/policy/it.BastionGuard.camera.policy
DESTINATION /usr/share/polkit-1/actions
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# ======================
# Permission Policy – Privacy Webcam
# ======================
install(FILES data/sudoers/bastionguard-helper
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# ======================
# Permission Policy – Bank helper
# ======================
install(FILES data/sudoers/bastionguard-helper
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# ======================
# Permission Policy – Helper anti-phishing-update
# ======================
install(FILES data/sudoers/bastionguard-phishing
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
install(PROGRAMS
data/scripts/bank-helper
DESTINATION /usr/bin/
)
# ======================
# Services
# ======================
# opzione per abilitare auto attivazione user units durante 'cmake --install' (default OFF)
# opzione per abilitare automaticamente le user units durante 'cmake --install' (default OFF)
option(ENABLE_USER_AGENT_AUTO "Attempt to enable systemd --user unit for logged-in users at install time" OFF)
# install system units (system-wide)
@ -1702,6 +2275,7 @@ install(FILES
data/service/BastionGuard-pacd.service
data/service/BastionGuard-cef.service
data/service/BastionGuard-mailproxy.service
data/service/BastionGuard-user-session-watch.service
DESTINATION /usr/lib/systemd/user
)
@ -1715,6 +2289,7 @@ install(PROGRAMS
data/scripts/BastionGuard-export-env.sh
data/scripts/BastionGuard-locale.sh
data/scripts/BastionGuard-setup-clamav-daemon.sh
data/scripts/BastionGuard-user-session-watch.sh
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data/scripts
)

4
debian/changelog vendored
View file

@ -1,5 +1,5 @@
bastionguard (1.1-1) stable; urgency=low
bastionguard (2.0-1) stable; urgency=low
* Debian package.
-- Calogero Scarnà <info@bastionguard.eu> Fri, 13 Mar 2026 12:00:00 +0100
-- Calogero Scarnà <info@bastionguard.eu> Fri, 12 Jun 2026 12:00:00 +0100

View file

@ -1,5 +1,5 @@
bastionguard (1.1-1ubuntu24.04.1) noble; urgency=low
bastionguard (2.0-1ubuntu24.04.1) noble; urgency=low
* Ubuntu 24.04 (Noble) package.
-- Calogero Scarnà <info@bastionguard.eu> Fri, 13 Mar 2026 12:00:00 +0100
-- Calogero Scarnà <info@bastionguard.eu> Fri, 12 Jun 2026 12:00:00 +0100

View file

@ -1,5 +1,5 @@
bastionguard (1.1-1ubuntu25.10) questing; urgency=low
bastionguard (2.0-1ubuntu25.10) questing; urgency=low
* Ubuntu 25.10 (Questing Quokka) package.
-- Calogero Scarnà <info@bastionguard.eu> Fri, 13 Mar 2026 12:00:00 +0100
-- Calogero Scarnà <info@bastionguard.eu> Fri, 12 Jun 2026 12:00:00 +0100

5
debian/changelog_ubuntu26 vendored Normal file
View file

@ -0,0 +1,5 @@
bastionguard (2.0-1ubuntu26.04) questing; urgency=low
* Ubuntu 26.04 (Resolute Raccoon) package.
-- Calogero Scarnà <info@bastionguard.eu> Fri, 12 Jun 2026 12:00:00 +0100

33
debian/control vendored
View file

@ -53,11 +53,38 @@ Build-Depends:
libasound2-dev,
libglibmm-2.4-dev,
libglibmm-2.68-dev,
libpangomm-2.48-dev,
gperf,
libxml2-dev,
libgstreamer1.0-dev,
libgstreamer-plugins-base1.0-dev,
libgstreamer-plugins-bad1.0-dev
libgstreamer-plugins-bad1.0-dev,
valac,
libgtk-4-dev,
libglib2.0-dev,
libjson-glib-dev,
libvte-2.91-gtk4-dev,
libgee-0.8-dev,
golang-go,
protobuf-compiler,
protobuf-compiler-grpc,
libprotobuf-dev,
libgrpc++-dev,
libshumate-dev,
libnetfilter-queue-dev,
libbpf-dev,
clang,
libgtk-3-dev,
help2man,
libbpf1,
libbpf-dev,
libbpf-tools,
bpftool,
libzstd-dev,
liblzo2-dev,
libvte-2.91-0,
libvte-2.91-dev,
gir1.2-vte-2.91
Standards-Version: 4.6.2
Rules-Requires-Root: no
Homepage: https://bastionguard.eu
@ -77,7 +104,9 @@ Depends:
dnsmasq,
rsync,
curl,
yara
yara,
libnss3,
libnss3-tools
Description: Transparent security control plane for Linux desktops
BastionGuard is not a "trust us" security product.
It is a security control plane for Linux desktops where every protection

View file

@ -51,11 +51,40 @@ Build-Depends: debhelper-compat (= 13),
wayland-protocols,
libasound2-dev,
libglibmm-2.4-dev,
libglibmm-2.68-dev,
libpangomm-2.48-dev,
gperf,
libxml2-dev,
libgstreamer1.0-dev,
libgstreamer-plugins-base1.0-dev,
libgstreamer-plugins-bad1.0-dev
libgstreamer-plugins-bad1.0-dev,
valac,
libgtk-4-dev,
libglib2.0-dev,
libjson-glib-dev,
libvte-2.91-gtk4-dev,
libgee-0.8-dev,
golang-go,
protobuf-compiler,
protobuf-compiler-grpc,
libprotobuf-dev,
libgrpc++-dev,
libshumate-dev,
libnetfilter-queue-dev,
libbpf-dev,
clang,
libgtk-3-dev,
help2man,
libbpf1,
libbpf-dev,
libbpf-tools,
linux-tools-common,
linux-tools-generic,
libzstd-dev,
liblzo2-dev,
libvte-2.91-0,
libvte-2.91-dev,
gir1.2-vte-2.91
Standards-Version: 4.6.2
Rules-Requires-Root: no
Homepage: https://bastionguard.eu
@ -72,7 +101,9 @@ Depends: ${shlibs:Depends}, ${misc:Depends},
dnsmasq,
rsync,
yara,
curl
curl,
libnss3,
libnss3-tools
Description: Transparent security control plane for Linux desktops
BastionGuard is not a "trust us" security product.
It is a security control plane for Linux desktops where every protection

View file

@ -53,11 +53,40 @@ Build-Depends: debhelper-compat (= 13),
wayland-protocols,
libasound2-dev,
libglibmm-2.4-dev,
libglibmm-2.68-dev,
libpangomm-2.48-dev,
gperf,
libxml2-dev,
libgstreamer1.0-dev,
libgstreamer-plugins-base1.0-dev,
libgstreamer-plugins-bad1.0-dev
libgstreamer-plugins-bad1.0-dev,
valac,
libgtk-4-dev,
libglib2.0-dev,
libjson-glib-dev,
libvte-2.91-gtk4-dev,
libgee-0.8-dev,
golang-go,
protobuf-compiler,
protobuf-compiler-grpc,
libprotobuf-dev,
libgrpc++-dev,
libshumate-dev,
libnetfilter-queue-dev,
libbpf-dev,
clang,
libgtk-3-dev,
help2man,
libbpf1,
libbpf-dev,
libbpf-tools,
linux-tools-common,
linux-tools-generic,
libzstd-dev,
liblzo2-dev,
libvte-2.91-0,
libvte-2.91-dev,
gir1.2-vte-2.91
Standards-Version: 4.6.2
Rules-Requires-Root: no
Homepage: https://bastionguard.eu
@ -74,7 +103,9 @@ Depends: ${shlibs:Depends}, ${misc:Depends},
dnsmasq,
rsync,
yara,
curl
curl,
libnss3,
libnss3-tools
Description: Transparent security control plane for Linux desktops
BastionGuard is not a "trust us" security product.
It is a security control plane for Linux desktops where every protection

119
debian/control_ubuntu26 vendored Normal file
View file

@ -0,0 +1,119 @@
Source: bastionguard
Section: utils
Priority: optional
Maintainer: Caogero Scarnà <info@bastionguard.eu>
Build-Depends: debhelper-compat (= 13),
build-essential,
cmake,
pkg-config,
gettext,
libgtkmm-4.0-dev,
libsigc++-3.0-dev,
libsoup-3.0-dev,
libsecret-1-dev,
libudev-dev,
libcups2,
libcups2-dev,
libidn2-dev,
libsqlite3-dev,
libcurl4-openssl-dev,
libssl-dev,
libboost-thread-dev,
libre2-dev,
libhyperscan-dev,
nlohmann-json3-dev,
libyara-dev,
libpolkit-gobject-1-dev,
libsmbclient-dev,
libsystemd-dev,
rsync,
meson,
ninja-build,
python3,
git,
libffi-dev,
zlib1g-dev,
libmount-dev,
libpcre2-dev,
libpng-dev,
libjpeg-dev,
libtiff-dev,
libwebp-dev,
libfribidi-dev,
libx11-dev,
libxcursor-dev,
libxrandr-dev,
libxi-dev,
libxinerama-dev,
libxdamage-dev,
libxcomposite-dev,
libxfixes-dev,
libxkbcommon-dev,
libwayland-dev,
wayland-protocols,
libasound2-dev,
libglibmm-2.4-dev,
libglibmm-2.68-dev,
libpangomm-2.48-dev,
gperf,
libxml2-dev,
libgstreamer1.0-dev,
libgstreamer-plugins-base1.0-dev,
libgstreamer-plugins-bad1.0-dev,
valac,
libgtk-4-dev,
libglib2.0-dev,
libjson-glib-dev,
libvte-2.91-gtk4-dev,
libgee-0.8-dev,
golang-go,
protobuf-compiler,
protobuf-compiler-grpc,
libprotobuf-dev,
libgrpc++-dev,
libshumate-dev,
libnetfilter-queue-dev,
libbpf-dev,
clang,
libgtk-3-dev,
help2man,
libbpf1,
libbpf-dev,
libbpf-tools,
linux-tools-common,
linux-tools-generic,
libzstd-dev,
liblzo2-dev,
libvte-2.91-0,
libvte-2.91-dev,
gir1.2-vte-2.91
Standards-Version: 4.6.2
Rules-Requires-Root: no
Homepage: https://bastionguard.eu
Package: bastionguard
Architecture: amd64
Depends: ${shlibs:Depends}, ${misc:Depends},
clamav,
clamav-daemon,
clamav-freshclam,
nginx,
php-fpm,
polkitd,
dnsmasq,
rsync,
yara,
curl,
libnss3,
libnss3-tools
Description: Transparent security control plane for Linux desktops
BastionGuard is not a "trust us" security product.
It is a security control plane for Linux desktops where every protection
mechanism is explicit, deterministic, and observable.
.
Unlike most desktop security tools, which hide decisions behind opaque
engines, cloud scoring, or silent automation, BastionGuard exposes
what is happening, why it is happening, and how protections are applied.
Users and administrators can see, control, and reason about every
security decision.

10
debian/rules vendored
View file

@ -23,12 +23,20 @@ override_dh_auto_configure:
override_dh_auto_build:
set -ex; \
dh_auto_build -- -j$$(nproc)
dh_auto_build -- -j1
override_dh_auto_install:
set -ex; \
dh_auto_install --destdir=debian/tmp
execute_after_dh_auto_install:
set -ex; \
rm -f debian/tmp/usr/share/icons/hicolor/icon-theme.cache
override_dh_strip:
set -ex; \
dh_strip --exclude=bsc_ebpf.o
override_dh_install:
set -ex; \
dh_install --sourcedir=debian/tmp

View file

@ -14,7 +14,7 @@ Name[pl]=Automatyczne uruchamianie BastionGuard
Name[pt]=Inicialização automática do BastionGuard
Name[ru]=Автозапуск BastionGuard
Comment=Protezione avanzata da ransomware, phishing e minacce in tempo reale
Comment=Advanced protection against ransomware, phishing, and real-time threats
Comment[ar]=حماية متقدمة ضد برامج الفدية والتصيد والتهديدات في الوقت الفعلي
Comment[de]=Erweiterter Schutz vor Ransomware, Phishing und Echtzeitbedrohungen
Comment[en_US]=Advanced protection against ransomware, phishing, and real-time threats

View file

@ -14,7 +14,7 @@ Name[pl]=Interfejs bankowy BastionGuard
Name[pt]=Interface bancária do BastionGuard
Name[ru]=Банковский интерфейс BastionGuard
Comment=Apri link bancari in Secure Browser
Comment=Open banking links in Secure Browser
Comment[ar]=افتح الروابط المصرفية في المتصفح الآمن
Comment[de]=Öffne Banklinks im sicheren Browser
Comment[en_US]=Open banking links in Secure Browser
@ -28,7 +28,7 @@ Comment[pt]=Abrir links bancários no navegador seguro
Comment[ru]=Открывать банковские ссылки в защищённом браузере
Exec=env LANGUAGE=${LANGUAGE} LANG=${LANG} LC_ALL=${LC_ALL} BastionGuard-bankgui
Icon=/usr/share/BastionGuard/data/logo.png
Icon=/usr/share/BastionGuard/data/bank-icon.svg
Terminal=false
Categories=Network;Security;
StartupNotify=true

View file

@ -14,7 +14,7 @@ Name[pl]=Bezpieczne płatności BastionGuard
Name[pt]=Pagamentos seguros BastionGuard
Name[ru]=Безопасные платежи BastionGuard
Comment=Apri link di pagamento ed e-commerce nel Secure Browser
Comment=Open payment and e-commerce links in Secure Browser
Comment[ar]=افتح روابط الدفع والتجارة الإلكترونية في المتصفح الآمن
Comment[de]=Öffne Zahlungs- und E-Commerce-Links im sicheren Browser
Comment[en_US]=Open payment and e-commerce links in Secure Browser
@ -28,7 +28,7 @@ Comment[pt]=Abrir links de pagamento e e-commerce no navegador seguro
Comment[ru]=Открывать ссылки оплаты и электронной коммерции в защищённом браузере
Exec=env LANGUAGE=${LANGUAGE} LANG=${LANG} LC_ALL=${LC_ALL} BastionGuard-secure-gui
Icon=/usr/share/BastionGuard/data/logo.png
Icon=/usr/share/BastionGuard/data/secure.svg
Terminal=false
Categories=Network;Security;WebBrowser;
StartupNotify=true

2
desktop/BastionGuard.desktop Executable file → Normal file
View file

@ -12,7 +12,7 @@ Name[pl]=BastionGuard
Name[pt]=BastionGuard
Name[ru]=BastionGuard
Comment=Protezione avanzata da ransomware, phishing e minacce in tempo reale
Comment=Advanced protection against ransomware, phishing, and real-time threats
Comment[ar]=حماية متقدمة ضد برامج الفدية والتصيد والتهديدات في الوقت الفعلي
Comment[de]=Erweiterter Schutz vor Ransomware, Phishing und Echtzeitbedrohungen
Comment[en_US]=Advanced protection against ransomware, phishing, and real-time threats

View file

@ -1,16 +1,34 @@
#
# Spec file for BastionGuard (Fedora)
# BastionGuard™
# Copyright (C) 2025–2026 Calogero Scarnà
#
# 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, version 3.
#
# 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, see <https://www.gnu.org/licenses/>.
#
# BastionGuard™ is a trademark of Calogero Scarnà.
# The BastionGuard™ name and branding are not licensed under the GPL.
#
Name: bastionguard
Version: 1.1
Version: 2.0
Release: 1%{?dist}
Summary: BastionGuard Security Platform
License: GPLv3
URL: https://git.bastionguard.eu/specialworld83/BastionGuard.git
Source0: %{name}-%{version}.tar.gz
Provides: bastionguard = %{version}-%{release}
Obsoletes: bastionguard < %{version}-%{release}
License: GPLv3
URL: https://git.bastionguard.eu/specialworld83/BastionGuard
Source0: %{name}-%{version}.tar.gz
%global debug_package %{nil}
BuildRequires: gcc-c++
@ -18,11 +36,15 @@ BuildRequires: cmake
BuildRequires: make
BuildRequires: pkgconf-pkg-config
BuildRequires: gettext
BuildRequires: python3
BuildRequires: rsync
BuildRequires: git
BuildRequires: systemd-rpm-macros
BuildRequires: gtkmm4.0-devel
BuildRequires: glibmm2.68-devel
BuildRequires: pangomm2.48-devel
BuildRequires: libsigc++30-devel
BuildRequires: libsoup3-devel
BuildRequires: libsecret-devel
BuildRequires: systemd-devel
@ -32,7 +54,7 @@ BuildRequires: libcurl-devel
BuildRequires: openssl-devel
BuildRequires: boost-devel
BuildRequires: re2-devel
BuildRequires: hyperscan-devel
BuildRequires: vectorscan-devel
BuildRequires: nlohmann-json-devel
BuildRequires: yara-devel
BuildRequires: polkit-devel
@ -58,6 +80,51 @@ BuildRequires: wayland-devel
BuildRequires: alsa-lib-devel
BuildRequires: pipewire-jack-audio-connection-kit-devel
BuildRequires: libsmbclient-devel
BuildRequires: libzstd-devel
BuildRequires: lzo-devel
BuildRequires: nginx
BuildRequires: php-fpm
BuildRequires: dnsmasq
BuildRequires: polkit
BuildRequires: rsync
BuildRequires: yara
BuildRequires: bubblewrap
BuildRequires: clamav
BuildRequires: clamav-freshclam
BuildRequires: clamd
BuildRequires: curl
BuildRequires: nss
BuildRequires: nss-tools
BuildRequires: sudo
# bastionguard-backup (fork GTK4 in Vala, build Meson)
BuildRequires: meson
BuildRequires: ninja-build
BuildRequires: vala
BuildRequires: gtk4-devel
BuildRequires: glib2-devel
BuildRequires: json-glib-devel
BuildRequires: vte291-gtk4-devel
BuildRequires: libgee-devel
BuildRequires: help2man
BuildRequires: vte291
BuildRequires: vte291-devel
# bastionguard-secure-connection (Meson + Go)
BuildRequires: golang
BuildRequires: protobuf-compiler
BuildRequires: protobuf-devel
BuildRequires: grpc-plugins
BuildRequires: grpc-devel
# SC GUI (mappa) + daemon eBPF
BuildRequires: libshumate-devel
BuildRequires: libnetfilter_queue-devel
BuildRequires: libbpf
BuildRequires: libbpf-devel
BuildRequires: libbpf-tools
BuildRequires: bpftool
BuildRequires: clang
BuildRequires: patchelf
Requires: nginx
Requires: php-fpm
@ -66,25 +133,25 @@ Requires: polkit
Requires: rsync
Requires: yara
Requires: bubblewrap
Requires: clamav
Requires: clamav-freshclam
Requires: clamd
Requires: curl
Requires: nss
Requires: nss-tools
Requires: sudo
%{?systemd_requires}
%description
Transparent security control plane for Linux desktops
Transparent security control plane for Linux desktops.
BastionGuard is not a "trust us" security product.
It is a security control plane for Linux desktops where every protection
mechanism is explicit, deterministic, and observable.
.
Unlike most desktop security tools, which hide decisions behind opaque
engines, cloud scoring, or silent automation, BastionGuard exposes
what is happening, why it is happening, and how protections are applied.
Users and administrators can see, control, and reason about every
security decision.
%prep
%autosetup -n %{name}-%{version}
%build
rm -rf build
@ -107,11 +174,15 @@ cmake .. \
-DINSTALL_NGINX_DEFAULTS=OFF \
-DBG_PACKAGING=ON \
-DBG_DEBIAN_NO_INSTALL_CODE=ON \
-DENABLE_CEF=ON \
-DENABLE_CEF_DAEMON=OFF \
-DENABLE_SYSTEM_CA_INSTALL=OFF \
-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
-DCMAKE_INSTALL_RPATH='\$ORIGIN/../share/BastionGuard/lib;\$ORIGIN/../share/BastionGuard/cef' \
-DCMAKE_INSTALL_RPATH='$ORIGIN/../share/BastionGuard/lib;$ORIGIN/../share/BastionGuard/cef' \
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=OFF
make %{?_smp_mflags}
make
%install
rm -rf %{buildroot}
@ -119,24 +190,64 @@ cd build
export DESTDIR=%{buildroot}
make install
# Sanity checks
# Fedora/RHEL family: il runtime CEF incorporato e le GUI Secure Browser
# devono essere presenti; daemon CEF, servizio, installazione CA e attivazione
# devono invece essere esclusi direttamente dal CMake.
for _forbidden in \
"%{buildroot}%{_bindir}/bastionguard-cef" \
"%{buildroot}%{_bindir}/bastionguard-activation-helper" \
"%{buildroot}%{_datadir}/polkit-1/actions/eu.bastionguard.install-ca.policy" \
"%{buildroot}%{_datadir}/polkit-1/actions/org.bastionguard.activation.policy" \
"%{buildroot}%{_datadir}/BastionGuard/data/scripts/install-ca-system.sh" \
"%{buildroot}%{_userunitdir}/BastionGuard-cef.service" \
"%{buildroot}%{_datadir}/BastionGuard/data/service/BastionGuard-cef.service" \
"%{buildroot}%{_unitdir}/bastionguard-cef.service"; do
test ! -e "$_forbidden"
done
# Le GUI e i launcher Secure Browser devono rimanere nel pacchetto.
for _required in \
"%{buildroot}%{_bindir}/BastionGuard-bankopener" \
"%{buildroot}%{_bindir}/BastionGuard-bankgui" \
"%{buildroot}%{_bindir}/BastionGuard-secure" \
"%{buildroot}%{_bindir}/BastionGuard-secure-gui" \
"%{buildroot}%{_datadir}/applications/BastionGuard-bankgui.desktop" \
"%{buildroot}%{_datadir}/applications/BastionGuard-secure.desktop" \
"%{buildroot}%{_datadir}/applications/bastionguard-bankopener.desktop"; do
test -e "$_required"
done
# Runtime CEF incorporato richiesto da BankOpener e Secure Browser.
test -d "%{buildroot}%{_datadir}/BastionGuard/cef"
install -dm750 %{buildroot}%{_sharedstatedir}/bastionguard-webui/{cache,quarantine,sessions,tmp}
install -dm755 %{buildroot}%{_localstatedir}/log/bastionguard-webui
test -x %{buildroot}%{_bindir}/BastionGuard
file %{buildroot}%{_bindir}/BastionGuard | grep -q "ELF 64-bit"
readelf -d %{buildroot}%{_bindir}/BastionGuard | grep -q NEEDED
%postun
if command -v systemctl >/dev/null 2>&1; then
systemctl daemon-reload >/dev/null 2>&1 || :
fi
:
%files
%{_bindir}/*
%{_datadir}/BastionGuard
%{_datadir}/bastionguard-backup
%{_datadir}/bastionguard-sc
%{_datadir}/applications/BastionGuard.desktop
%{_datadir}/applications/bastionguard-sc.desktop
%{_datadir}/applications/bastionguard-backup-gtk.desktop
%{_datadir}/applications/BastionGuard-bankgui.desktop
%{_datadir}/applications/BastionGuard-secure.desktop
%{_datadir}/applications/bastionguard-bankopener.desktop
%config(noreplace) %{_sysconfdir}/xdg/autostart/BastionGuard-autostart.desktop
%config(noreplace) %{_sysconfdir}/xdg/autostart/bastionguard-sc-autostart.desktop
%{_datadir}/dbus-1/services/org.BastionGuard.RansomwareAlert.service
%{_datadir}/dbus-1/system-services/org.BastionGuard.USBD.service
@ -146,15 +257,47 @@ readelf -d %{buildroot}%{_bindir}/BastionGuard | grep -q NEEDED
%{_datadir}/polkit-1/actions/org.BastionGuard.policy
%{_datadir}/polkit-1/actions/org.BastionGuard.ransomware.policy
%{_datadir}/polkit-1/actions/org.BastionGuard.USBD.policy
%{_datadir}/polkit-1/actions/eu.bastionguard.sc.policy
%{_datadir}/polkit-1/actions/org.bastionguard.pkexec.backup.policy
%{_unitdir}/*
%{_userunitdir}/*
/usr/share/locale/*
/usr/share/icons/*
/usr/share/plymouth/*
/etc/bastionguard-backup/*
/usr/lib/bastionguard-sc/*
/usr/share/metainfo/*
/usr/share/man/*
/usr/share/icons/hicolor/*/apps/*
%dir %{_libexecdir}/bastionguard
%{_libexecdir}/bastionguard/archive_worker
%config(noreplace) %{_sysconfdir}/sudoers.d/bastionguard-helper
%config(noreplace) %{_sysconfdir}/sudoers.d/bastionguard-phishing
%config(noreplace) %{_sysconfdir}/sudoers.d/bastionguard-bank
%dir %attr(750,apache,apache) %{_sharedstatedir}/bastionguard-webui
%dir %attr(750,apache,apache) %{_sharedstatedir}/bastionguard-webui/cache
%dir %attr(750,apache,apache) %{_sharedstatedir}/bastionguard-webui/quarantine
%dir %attr(750,apache,apache) %{_sharedstatedir}/bastionguard-webui/sessions
%dir %attr(750,apache,apache) %{_sharedstatedir}/bastionguard-webui/tmp
%dir %attr(755,root,root) %{_localstatedir}/log/bastionguard-webui
# ── BastionGuard Recovery Data ──────────────────────────────
%{_datadir}/bastionguard-recovery-data
%{_datadir}/applications/com.bastionguard.RecoveryData.desktop
%{_datadir}/polkit-1/actions/com.bastionguard.RecoveryData.policy
%{_datadir}/locale/*/LC_MESSAGES/bastionguard-recovery-data.mo
# ── Plymouth theme ──────────────────────────────────────────
%{_datadir}/plymouth/themes/bastionguard
%{_datadir}/pixmaps/*
# ── BastionGuard Secure Connection: config daemon ───────────
%dir %{_sysconfdir}/bastionguard-secure-connectiond
%config(noreplace) %{_sysconfdir}/bastionguard-secure-connectiond/*
%changelog
* Fri Mar 13 2026 Calogero Scarnà <info@bastionguard.eu> - 1.1-1
- Update package, view changelog
* Fri Jun 12 2026 Calogero Scarnà <info@bastionguard.eu> - 2.0
- Update package

View file

@ -1,6 +1,89 @@
cmake_minimum_required(VERSION 3.16)
project(BastionGuard LANGUAGES CXX)
# ============================================================
# CEF feature split
# - ENABLE_CEF: runtime CEF + Secure Browser GUI/launchers
# - ENABLE_CEF_DAEMON: standalone bastionguard-cef proxy + user unit
# - ENABLE_SYSTEM_CA_INSTALL: system CA policy/helper/script
# ============================================================
option(ENABLE_CEF
"Build and install the embedded CEF runtime and Secure Browser components"
ON)
option(ENABLE_CEF_DAEMON
"Build and install the standalone bastionguard-cef proxy and user service"
ON)
option(ENABLE_SYSTEM_CA_INSTALL
"Install the system CA policy and install-ca-system.sh helper"
ON)
set(BG_OS_RELEASE_FILE "/etc/os-release" CACHE FILEPATH
"os-release file used for distro-specific build decisions")
set(BG_FEDORA_RHEL_FAMILY FALSE)
if(EXISTS "${BG_OS_RELEASE_FILE}")
file(STRINGS "${BG_OS_RELEASE_FILE}" BG_OS_RELEASE_LINES
REGEX "^(ID|ID_LIKE)=")
foreach(BG_OS_LINE IN LISTS BG_OS_RELEASE_LINES)
string(REPLACE "\"" "" BG_OS_LINE "${BG_OS_LINE}")
string(TOLOWER "${BG_OS_LINE}" BG_OS_LINE_LOWER)
if(BG_OS_LINE_LOWER MATCHES
"(^|[ =])(fedora|rhel|redhat|centos|almalinux|alma|rocky|rockylinux|ol)([ ]|$)")
set(BG_FEDORA_RHEL_FAMILY TRUE)
endif()
endforeach()
endif()
# Fedora/RHEL-family keeps the embedded CEF runtime required by
# BankOpener/BankGUI/Secure/SecureGUI, but never builds the standalone
# CEF proxy and never installs a system CA.
if(BG_FEDORA_RHEL_FAMILY)
set(ENABLE_CEF_DAEMON OFF CACHE BOOL
"Build and install the standalone bastionguard-cef proxy and user service"
FORCE)
set(ENABLE_SYSTEM_CA_INSTALL OFF CACHE BOOL
"Install the system CA policy and install-ca-system.sh helper"
FORCE)
message(STATUS
"[CEF] Fedora/RHEL family: embedded Secure Browser enabled; CEF daemon and system CA disabled")
endif()
# The daemon and CA installer cannot exist without the embedded CEF runtime.
if(NOT ENABLE_CEF)
set(ENABLE_CEF_DAEMON OFF CACHE BOOL
"Build and install the standalone bastionguard-cef proxy and user service"
FORCE)
set(ENABLE_SYSTEM_CA_INSTALL OFF CACHE BOOL
"Install the system CA policy and install-ca-system.sh helper"
FORCE)
endif()
if(ENABLE_CEF)
add_compile_definitions(BASTIONGUARD_HAS_CEF=1)
else()
add_compile_definitions(BASTIONGUARD_HAS_CEF=0)
endif()
if(ENABLE_CEF_DAEMON)
add_compile_definitions(BASTIONGUARD_HAS_CEF_DAEMON=1)
else()
add_compile_definitions(BASTIONGUARD_HAS_CEF_DAEMON=0)
endif()
if(ENABLE_SYSTEM_CA_INSTALL)
add_compile_definitions(BASTIONGUARD_ALLOW_SYSTEM_CA_INSTALL=1)
else()
add_compile_definitions(BASTIONGUARD_ALLOW_SYSTEM_CA_INSTALL=0)
endif()
message(STATUS "ENABLE_CEF = ${ENABLE_CEF}")
message(STATUS "ENABLE_CEF_DAEMON = ${ENABLE_CEF_DAEMON}")
message(STATUS "ENABLE_SYSTEM_CA_INSTALL = ${ENABLE_SYSTEM_CA_INSTALL}")
message(STATUS "BG_FEDORA_RHEL_FAMILY = ${BG_FEDORA_RHEL_FAMILY}")
set(Boost_NO_BOOST_CMAKE ON)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
@ -90,9 +173,17 @@ endfunction()
# In RPM: niente path assoluti in RUNPATH/RPATH, usa $ORIGIN
if(BG_PACKAGING)
# binari in /usr/bin → librerie in /usr/share/BastionGuard/*
set(BG_INSTALL_RPATH "\$ORIGIN/../share/BastionGuard/lib;\$ORIGIN/../share/BastionGuard/cef")
if(ENABLE_CEF)
set(BG_INSTALL_RPATH "\$ORIGIN/../share/BastionGuard/lib;\$ORIGIN/../share/BastionGuard/cef")
else()
set(BG_INSTALL_RPATH "\$ORIGIN/../share/BastionGuard/lib")
endif()
else()
set(BG_INSTALL_RPATH "/usr/share/BastionGuard/lib;/usr/share/BastionGuard/cef")
if(ENABLE_CEF)
set(BG_INSTALL_RPATH "/usr/share/BastionGuard/lib;/usr/share/BastionGuard/cef")
else()
set(BG_INSTALL_RPATH "/usr/share/BastionGuard/lib")
endif()
endif()
# Evita che CMake “trascini” path di link nell'RPATH
@ -140,7 +231,19 @@ function(bg_set_rpath target)
endif()
endif()
endfunction()
# ======================
# libsystemd / sd-bus
# ======================
pkg_check_modules(SYSTEMD REQUIRED libsystemd)
if (SYSTEMD_FOUND)
message(STATUS "✔ libsystemd trovato: ${SYSTEMD_VERSION}")
include_directories(${SYSTEMD_INCLUDE_DIRS})
link_directories(${SYSTEMD_LIBRARY_DIRS})
add_definitions(${SYSTEMD_CFLAGS_OTHER})
else()
message(FATAL_ERROR "❌ libsystemd non trovato. Installa libsystemd-dev")
endif()
# ======================
# systemd (sd-bus) — necessario su Debian/Ubuntu recenti (DSO missing)
# ======================
@ -191,7 +294,11 @@ endif()
# Option to control whether systemd services are enabled / started at install time.
option(ENABLE_SYSTEMD_SERVICES "Enable and start systemd services at install time" OFF)
install(DIRECTORY data/ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data)
install(DIRECTORY data/
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data
PATTERN "scripts/install-ca-system.sh" EXCLUDE
PATTERN "service/BastionGuard-cef.service" EXCLUDE
)
set(INSTALL_DATA_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/BastionGuard/data")
set(INSTALL_LOCALE_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/BastionGuard/locale")
@ -465,6 +572,36 @@ target_link_libraries(identity_leak
nlohmann_json::nlohmann_json
)
# ======================
# Password Manager Module
# ======================
set(PASSWORD_MANAGER_SOURCES
src/password_manager/PasswordEntry.cpp
src/password_manager/PasswordVault.cpp
src/password_manager/PasswordGenerator.cpp
src/password_manager/PasswordDialogs.cpp
src/password_manager/PasswordSearchRow.cpp
src/password_manager/PasswordManagerPage.cpp
src/password_manager/PasswordImporter.cpp
src/password_manager/PasswordImportDialog.cpp
src/password_manager/PasswordVaultView.cpp
)
add_library(password_manager STATIC ${PASSWORD_MANAGER_SOURCES})
target_include_directories(password_manager PUBLIC
src
src/password_manager
)
target_link_libraries(password_manager
PUBLIC
${GTKMM_LIBRARIES}
${GIOMM_LIBRARIES}
${SIGC_LIBRARIES}
${LIBSECRET_LIBRARIES}
nlohmann_json::nlohmann_json
)
# ======================
# RE2 (opzionale, per regex sicure e veloci)
@ -536,10 +673,8 @@ set(BastionGuard_SOURCES
src/StyleProvider.cpp
src/AntiRansomEngine.cpp
src/AntiPhishingEngine.cpp
src/BankPage.cpp
src/wizard/wizard_window.cpp
src/wizard/wizard_setup.cpp
src/SecureBrowser.cpp
src/PrivacyPage.cpp
src/AurScan.cpp
src/SettingsWindow.cpp
@ -555,8 +690,20 @@ set(BastionGuard_SOURCES
src/usb/LiveScanDialog.cpp
src/phishing_search/PhishingPage.cpp
src/phishing_search/PhishingCheckCard.cpp
src/vpn/VpnPage.cpp
src/vpn/WireguardBackend.cpp
src/password_manager/PasswordManagerPage.cpp
src/backup/BackupPage.cpp
src/Utils.cpp
)
if(ENABLE_CEF)
list(APPEND BastionGuard_SOURCES
src/BankPage.cpp
src/SecureBrowser.cpp
)
endif()
add_executable(BastionGuard ${BastionGuard_SOURCES})
target_include_directories(BastionGuard
PRIVATE
@ -567,8 +714,8 @@ target_include_directories(BastionGuard
target_compile_definitions(BastionGuard PRIVATE
BASTIONGUARD_VERSION="1.1"
BASTIONGUARD_BUILD=20260310
BASTIONGUARD_VERSION="2.0"
BASTIONGUARD_BUILD=20260411
)
target_link_libraries(BastionGuard
@ -585,12 +732,15 @@ target_link_libraries(BastionGuard
phishing_common
firewall
identity_leak
password_manager
CURL::libcurl
OpenSSL::SSL
OpenSSL::Crypto
)
target_link_options(BastionGuard PRIVATE -lsystemd)
bg_set_rpath(BastionGuard)
bg_link_systemd(BastionGuard)
if(ENABLE_CEF)
# ============================================================
# Blink / CEF Integration (SecureBrowser)
# ============================================================
@ -699,8 +849,6 @@ message(STATUS "✔ Wrapper statico CEF trovato: ${CEF_WRAPPER}")
# ------------------------------------------------------------
# Aggiungi SecureBrowser
# ------------------------------------------------------------
list(APPEND BastionGuard_SOURCES src/SecureBrowser.cpp)
include_directories(${CEF_ROOT} ${CEF_ROOT}/include)
target_link_libraries(BastionGuard
@ -765,6 +913,8 @@ bg_install_code( "
execute_process(COMMAND chmod 4755 ${CMAKE_INSTALL_FULL_DATAROOTDIR}/BastionGuard/cef/chrome-sandbox)
")
endif()
# ============================================================
# Optional Polkit integration
# ============================================================
@ -796,6 +946,7 @@ set(RANSW_ALERT_SOURCES
src/AntiRansomEngine.cpp
src/AntiPhishingEngine.cpp
src/Quarantine.cpp
src/Utils.cpp
)
add_executable(BastionGuard-ransomware-alert ${RANSW_ALERT_SOURCES})
@ -832,6 +983,7 @@ set(RANSW_REALTIME_ALERT_SOURCES
src/AntiRansomEngine.cpp
src/AntiPhishingEngine.cpp
src/Quarantine.cpp
src/Utils.cpp
)
add_executable(BastionGuard-ransomware-realtime-alert ${RANSW_REALTIME_ALERT_SOURCES})
@ -1020,6 +1172,7 @@ set(WIZARD_SOURCES
src/wizard/wizard_setup.cpp
src/wizard/main.cpp
src/wizard/StyleProvider.cpp
src/Utils.cpp
)
add_executable(BastionGuard-wizard ${WIZARD_SOURCES})
@ -1226,6 +1379,7 @@ install(TARGETS BastionGuard-usbd RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if(ENABLE_CEF)
# ======================
# BankOpener (wrapper sandbox sicuro)
# ======================
@ -1287,6 +1441,8 @@ bg_set_rpath(BastionGuard-bankgui)
install(TARGETS BastionGuard-bankgui RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
# ======================
# Pagamenti sicuri
# ======================
@ -1302,6 +1458,7 @@ install(TARGETS bastionguard-pacd RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if(ENABLE_CEF AND ENABLE_CEF_DAEMON)
# ======================
# BastionGuard CEF Proxy (bastionguard-cef)
# ======================
@ -1358,13 +1515,13 @@ target_link_libraries(bastionguard-cef
PRIVATE
${BG_BOOST_HEADERS}
Threads::Threads
OpenSSL::SSL
OpenSSL::Crypto
${GTKMM_LIBRARIES}
${GIOMM_LIBRARIES}
${SIGC_LIBRARIES}
${SOUP_LIBRARIES}
${GLIB_LIBRARIES}
${CEF_LIB}
${CEF_WRAPPER}
@ -1376,6 +1533,9 @@ bg_set_rpath(bastionguard-cef)
install(TARGETS bastionguard-cef RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(ENABLE_CEF)
# ======================
# BastionGuard Secure Payments
# - BastionGuard-secure (CLI opener)
@ -1457,6 +1617,7 @@ install(TARGETS BastionGuard-secure RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# ---- GUI selector ----
add_executable(BastionGuard-secure-gui
src/payment_secure/BastionGuard-secure-main.cpp
src/payment_secure/dns_secure.cpp
src/StyleProvider.cpp
)
@ -1492,6 +1653,7 @@ endif()
install(TARGETS BastionGuard-secure-gui RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
# ======================
# BastionGuard-mailproxy — proxy SMTP utente
@ -1533,6 +1695,495 @@ install(FILES
DESTINATION /usr/lib/systemd/user
)
# ============================================================
# BastionGuard WebUI
# ============================================================
set(BG_WEBUI_SOURCE_DIR "${CMAKE_SOURCE_DIR}/webui")
set(BG_WEBUI_BUILD_DIR "${CMAKE_BINARY_DIR}/webui")
set(BG_WEBUI_STAMP "${BG_WEBUI_BUILD_DIR}/.webui-staged")
if(EXISTS "${BG_WEBUI_SOURCE_DIR}/index.php")
add_custom_command(
OUTPUT "${BG_WEBUI_STAMP}"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${BG_WEBUI_SOURCE_DIR}"
"${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E touch "${BG_WEBUI_STAMP}"
DEPENDS "${BG_WEBUI_SOURCE_DIR}/index.php"
COMMENT "Staging BastionGuard WebUI into the build directory"
VERBATIM
)
add_custom_target(BastionGuard-webui ALL
DEPENDS "${BG_WEBUI_STAMP}"
)
install(DIRECTORY "${BG_WEBUI_BUILD_DIR}/"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/webui"
USE_SOURCE_PERMISSIONS
COMPONENT webui
PATTERN ".git" EXCLUDE
PATTERN "*.bak" EXCLUDE
PATTERN "*.tmp" EXCLUDE
PATTERN ".webui-staged" EXCLUDE
)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/data/vhosts/webui/"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data/vhosts/webui"
USE_SOURCE_PERMISSIONS
COMPONENT webui
OPTIONAL
)
install(CODE "
message(STATUS \"[WebUI] Installed in: ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/webui\")
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/cache)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/quarantine)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/sessions)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/tmp)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/log/bastionguard-webui)
")
else()
message(WARNING "BastionGuard WebUI source not found at ${BG_WEBUI_SOURCE_DIR}; WebUI will not be installed.")
endif()
# ======================
# BastionGuard Backup (fork di Timeshift, build via Meson)
# ======================
option(ENABLE_BASTIONGUARD_BACKUP "Build bastionguard-backup (Timeshift fork)" ON)
if(ENABLE_BASTIONGUARD_BACKUP)
include(ExternalProject)
find_program(MESON_EXECUTABLE meson REQUIRED)
find_program(NINJA_EXECUTABLE ninja REQUIRED)
find_program(VALAC_EXECUTABLE valac REQUIRED)
find_program(PKG_CONFIG_EXECUTABLE pkg-config REQUIRED)
# Dipendenze runtime/build del fork
pkg_check_modules(BG_BACKUP_GTK3 REQUIRED gtk+-3.0)
pkg_check_modules(BG_BACKUP_GIO REQUIRED gio-2.0 gio-unix-2.0)
pkg_check_modules(BG_BACKUP_JSON REQUIRED json-glib-1.0)
pkg_check_modules(BG_BACKUP_VTE REQUIRED vte-2.91)
pkg_check_modules(BG_BACKUP_GEE REQUIRED gee-0.8)
set(BG_BACKUP_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-backup")
set(BG_BACKUP_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-backup-build")
set(BG_BACKUP_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-backup-install")
message(STATUS "[BG-Backup] Source dir : ${BG_BACKUP_SOURCE_DIR}")
message(STATUS "[BG-Backup] Build dir : ${BG_BACKUP_BINARY_DIR}")
message(STATUS "[BG-Backup] Stage dir : ${BG_BACKUP_INSTALL_DIR}")
message(STATUS "[BG-Backup] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_backup_ext
SOURCE_DIR "${BG_BACKUP_SOURCE_DIR}"
BINARY_DIR "${BG_BACKUP_BINARY_DIR}"
CONFIGURE_COMMAND
${MESON_EXECUTABLE} setup "${BG_BACKUP_BINARY_DIR}" "${BG_BACKUP_SOURCE_DIR}"
--prefix=/usr
--buildtype=release
--reconfigure
BUILD_COMMAND
${MESON_EXECUTABLE} compile -C "${BG_BACKUP_BINARY_DIR}"
INSTALL_COMMAND
${MESON_EXECUTABLE} install -C "${BG_BACKUP_BINARY_DIR}" --destdir "${BG_BACKUP_INSTALL_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-backup ALL
DEPENDS bastionguard_backup_ext
)
install(CODE "
set(BG_BACKUP_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-Backup] =====================================\")
message(STATUS \"[BG-Backup] Installazione bastionguard-backup\")
message(STATUS \"[BG-Backup] Stage dir Meson : ${BG_BACKUP_INSTALL_DIR}\")
message(STATUS \"[BG-Backup] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-Backup] DESTDIR : \${BG_BACKUP_DESTDIR}\")
message(STATUS \"[BG-Backup]\")
set(BG_BACKUP_STAGE_BIN \"${BG_BACKUP_INSTALL_DIR}/usr/bin\")
set(BG_BACKUP_STAGE_SHARE \"${BG_BACKUP_INSTALL_DIR}/usr/share\")
set(BG_BACKUP_STAGE_ETC \"${BG_BACKUP_INSTALL_DIR}/etc\")
set(BG_BACKUP_DEST_BIN \"\${BG_BACKUP_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_BACKUP_DEST_SHARE \"\${BG_BACKUP_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_BACKUP_DEST_ETC \"\${BG_BACKUP_DESTDIR}/etc\")
message(STATUS \"[BG-Backup] Copia binari : \${BG_BACKUP_STAGE_BIN} -> \${BG_BACKUP_DEST_BIN}\")
if(EXISTS \"\${BG_BACKUP_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_BIN}\"
\"\${BG_BACKUP_DEST_BIN}\"
RESULT_VARIABLE BG_BACKUP_BIN_RES
)
if(NOT BG_BACKUP_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando i binari in \${BG_BACKUP_DEST_BIN}\")
endif()
else()
message(WARNING \"[BG-Backup] Directory bin non trovata: \${BG_BACKUP_STAGE_BIN}\")
endif()
message(STATUS \"[BG-Backup] Copia share : \${BG_BACKUP_STAGE_SHARE} -> \${BG_BACKUP_DEST_SHARE}\")
if(EXISTS \"\${BG_BACKUP_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_SHARE}\"
\"\${BG_BACKUP_DEST_SHARE}\"
RESULT_VARIABLE BG_BACKUP_SHARE_RES
)
if(NOT BG_BACKUP_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando share in \${BG_BACKUP_DEST_SHARE}\")
endif()
else()
message(WARNING \"[BG-Backup] Directory share non trovata: \${BG_BACKUP_STAGE_SHARE}\")
endif()
message(STATUS \"[BG-Backup] Copia etc : \${BG_BACKUP_STAGE_ETC} -> \${BG_BACKUP_DEST_ETC}\")
if(EXISTS \"\${BG_BACKUP_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_ETC}\"
\"\${BG_BACKUP_DEST_ETC}\"
RESULT_VARIABLE BG_BACKUP_ETC_RES
)
if(NOT BG_BACKUP_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando etc in \${BG_BACKUP_DEST_ETC}\")
endif()
else()
message(STATUS \"[BG-Backup] Nessuna directory etc da installare\")
endif()
message(STATUS \"[BG-Backup] ✔ installazione completata\")
message(STATUS \"[BG-Backup] =====================================\")
")
endif()
# ======================
# BastionGuard Secure Connection (Meson + Go)
# ======================
option(ENABLE_BASTIONGUARD_SECURE_CONNECTION "Build bastionguard-secure-connection" ON)
if(ENABLE_BASTIONGUARD_SECURE_CONNECTION)
include(ExternalProject)
find_program(MESON_EXECUTABLE meson REQUIRED)
find_program(NINJA_EXECUTABLE ninja REQUIRED)
find_program(GO_EXECUTABLE go REQUIRED)
find_program(PROTOC_EXECUTABLE protoc REQUIRED)
find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin REQUIRED)
find_program(PKG_CONFIG_EXECUTABLE pkg-config REQUIRED)
set(BG_SC_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-secure-connection")
set(BG_SC_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-secure-connection-build")
set(BG_SC_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-secure-connection-install")
message(STATUS "[BG-SC] Source dir : ${BG_SC_SOURCE_DIR}")
message(STATUS "[BG-SC] Build dir : ${BG_SC_BINARY_DIR}")
message(STATUS "[BG-SC] Stage dir : ${BG_SC_INSTALL_DIR}")
message(STATUS "[BG-SC] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_secure_connection_ext
SOURCE_DIR "${BG_SC_SOURCE_DIR}"
BINARY_DIR "${BG_SC_BINARY_DIR}"
CONFIGURE_COMMAND
${MESON_EXECUTABLE} setup "${BG_SC_BINARY_DIR}" "${BG_SC_SOURCE_DIR}"
--prefix=/usr
--sysconfdir=/etc
--localedir=share/locale
--buildtype=release
--reconfigure
BUILD_COMMAND
${MESON_EXECUTABLE} compile -C "${BG_SC_BINARY_DIR}"
INSTALL_COMMAND
${MESON_EXECUTABLE} install -C "${BG_SC_BINARY_DIR}" --destdir "${BG_SC_INSTALL_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-secure-connection ALL
DEPENDS bastionguard_secure_connection_ext
)
install(CODE "
set(BG_SC_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-SC] =====================================\")
message(STATUS \"[BG-SC] Installazione bastionguard-secure-connection\")
message(STATUS \"[BG-SC] Stage dir Meson : ${BG_SC_INSTALL_DIR}\")
message(STATUS \"[BG-SC] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-SC] DESTDIR : \${BG_SC_DESTDIR}\")
set(BG_SC_STAGE_BIN \"${BG_SC_INSTALL_DIR}/usr/bin\")
set(BG_SC_STAGE_SHARE \"${BG_SC_INSTALL_DIR}/usr/share\")
set(BG_SC_STAGE_ETC \"${BG_SC_INSTALL_DIR}/etc\")
set(BG_SC_STAGE_LIB \"${BG_SC_INSTALL_DIR}/usr/lib\")
set(BG_SC_DEST_BIN \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_SC_DEST_SHARE \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_SC_DEST_ETC \"\${BG_SC_DESTDIR}/etc\")
set(BG_SC_DEST_LIB \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/lib\")
if(EXISTS \"\${BG_SC_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_BIN}\"
\"\${BG_SC_DEST_BIN}\"
RESULT_VARIABLE BG_SC_BIN_RES
)
if(NOT BG_SC_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando i binari\")
endif()
endif()
if(EXISTS \"\${BG_SC_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_SHARE}\"
\"\${BG_SC_DEST_SHARE}\"
RESULT_VARIABLE BG_SC_SHARE_RES
)
if(NOT BG_SC_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando share\")
endif()
endif()
if(EXISTS \"\${BG_SC_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_ETC}\"
\"\${BG_SC_DEST_ETC}\"
RESULT_VARIABLE BG_SC_ETC_RES
)
if(NOT BG_SC_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando etc\")
endif()
endif()
# ── Copia esplicita config daemon in /etc/bastionguard-secure-connectiond ──
# Meson installa i JSON con sysconfdir=/etc (assoluto), quindi nella stage
# finiscono sempre in <INSTALL_DIR>/etc/bastionguard-secure-connectiond/.
# Con DESTDIR finiscono dentro il pkgdir, senza DESTDIR in /etc di sistema.
set(BG_SC_CONF_SRC \"${BG_SC_INSTALL_DIR}/etc/bastionguard-secure-connectiond\")
set(BG_SC_CONF_DST \"\${BG_SC_DESTDIR}/etc/bastionguard-secure-connectiond\")
if(EXISTS \"\${BG_SC_CONF_SRC}\")
file(MAKE_DIRECTORY \"\${BG_SC_CONF_DST}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_CONF_SRC}\"
\"\${BG_SC_CONF_DST}\"
RESULT_VARIABLE BG_SC_CONF_RES
)
if(NOT BG_SC_CONF_RES EQUAL 0)
message(WARNING \"[BG-SC] Impossibile copiare la config (permessi?): \${BG_SC_CONF_DST}\")
else()
message(STATUS \"[BG-SC] ✔ Config daemon installata: \${BG_SC_CONF_DST}\")
endif()
else()
message(WARNING \"[BG-SC] Directory config non trovata nella stage: \${BG_SC_CONF_SRC}\")
endif()
# ── Copia esplicita autostart in /etc/xdg/autostart ──────────────────
set(BG_SC_AUTOSTART_SRC
\"${BG_SC_INSTALL_DIR}/etc/xdg/autostart/bastionguard-sc-autostart.desktop\")
set(BG_SC_AUTOSTART_DST \"\${BG_SC_DESTDIR}/etc/xdg/autostart/bastionguard-sc-autostart.desktop\")
if(EXISTS \"\${BG_SC_AUTOSTART_SRC}\")
file(MAKE_DIRECTORY \"\${BG_SC_DESTDIR}/etc/xdg/autostart\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy
\"\${BG_SC_AUTOSTART_SRC}\"
\"\${BG_SC_AUTOSTART_DST}\"
RESULT_VARIABLE BG_SC_AUTOSTART_RES
)
if(NOT BG_SC_AUTOSTART_RES EQUAL 0)
message(WARNING \"[BG-SC] Impossibile copiare l'autostart (permessi?): \${BG_SC_AUTOSTART_DST}\")
else()
message(STATUS \"[BG-SC] ✔ Autostart installato: \${BG_SC_AUTOSTART_DST}\")
endif()
else()
message(WARNING \"[BG-SC] File autostart non trovato nella stage: \${BG_SC_AUTOSTART_SRC}\")
endif()
if(EXISTS \"\${BG_SC_STAGE_LIB}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_LIB}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_LIB}\"
\"\${BG_SC_DEST_LIB}\"
RESULT_VARIABLE BG_SC_LIB_RES
)
if(NOT BG_SC_LIB_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando lib\")
endif()
endif()
message(STATUS \"[BG-SC] ✔ installazione completata\")
message(STATUS \"[BG-SC] =====================================\")
")
endif()
# ======================
# BastionGuard Recovery Data (CMake)
# ======================
option(ENABLE_BASTIONGUARD_RECOVERY_DATA "Build bastionguard-recovery-data" ON)
if(ENABLE_BASTIONGUARD_RECOVERY_DATA)
include(ExternalProject)
set(BG_RD_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-recovery-data")
set(BG_RD_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-recovery-data-build")
set(BG_RD_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-recovery-data-install")
message(STATUS "[BG-RD] Source dir : ${BG_RD_SOURCE_DIR}")
message(STATUS "[BG-RD] Build dir : ${BG_RD_BINARY_DIR}")
message(STATUS "[BG-RD] Stage dir : ${BG_RD_INSTALL_DIR}")
message(STATUS "[BG-RD] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_recovery_data_ext
SOURCE_DIR "${BG_RD_SOURCE_DIR}"
BINARY_DIR "${BG_RD_BINARY_DIR}"
CONFIGURE_COMMAND
"${CMAKE_COMMAND}" -S "${BG_RD_SOURCE_DIR}" -B "${BG_RD_BINARY_DIR}"
-DCMAKE_INSTALL_PREFIX=/usr
-DCMAKE_BUILD_TYPE=Release
BUILD_COMMAND
"${CMAKE_COMMAND}" --build "${BG_RD_BINARY_DIR}" --parallel
INSTALL_COMMAND
"${CMAKE_COMMAND}" -E env DESTDIR=${BG_RD_INSTALL_DIR}
"${CMAKE_COMMAND}" --install "${BG_RD_BINARY_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-recovery-data ALL
DEPENDS bastionguard_recovery_data_ext
)
install(CODE "
set(BG_RD_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-RD] =====================================\")
message(STATUS \"[BG-RD] Installazione bastionguard-recovery-data\")
message(STATUS \"[BG-RD] Stage dir CMake : ${BG_RD_INSTALL_DIR}\")
message(STATUS \"[BG-RD] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-RD] DESTDIR : \${BG_RD_DESTDIR}\")
set(BG_RD_STAGE_BIN \"${BG_RD_INSTALL_DIR}/usr/bin\")
set(BG_RD_STAGE_SHARE \"${BG_RD_INSTALL_DIR}/usr/share\")
set(BG_RD_STAGE_ETC \"${BG_RD_INSTALL_DIR}/etc\")
set(BG_RD_STAGE_LIB \"${BG_RD_INSTALL_DIR}/usr/lib\")
set(BG_RD_DEST_BIN \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_RD_DEST_SHARE \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_RD_DEST_ETC \"\${BG_RD_DESTDIR}/etc\")
set(BG_RD_DEST_LIB \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/lib\")
if(EXISTS \"\${BG_RD_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_BIN}\"
\"\${BG_RD_DEST_BIN}\"
RESULT_VARIABLE BG_RD_BIN_RES
)
if(NOT BG_RD_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando i binari\")
endif()
else()
message(WARNING \"[BG-RD] Directory bin non trovata: \${BG_RD_STAGE_BIN}\")
endif()
if(EXISTS \"\${BG_RD_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_SHARE}\"
\"\${BG_RD_DEST_SHARE}\"
RESULT_VARIABLE BG_RD_SHARE_RES
)
if(NOT BG_RD_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando share\")
endif()
else()
message(WARNING \"[BG-RD] Directory share non trovata: \${BG_RD_STAGE_SHARE}\")
endif()
if(EXISTS \"\${BG_RD_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_ETC}\"
\"\${BG_RD_DEST_ETC}\"
RESULT_VARIABLE BG_RD_ETC_RES
)
if(NOT BG_RD_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando etc\")
endif()
else()
message(STATUS \"[BG-RD] Nessuna directory etc da installare\")
endif()
if(EXISTS \"\${BG_RD_STAGE_LIB}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_LIB}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_LIB}\"
\"\${BG_RD_DEST_LIB}\"
RESULT_VARIABLE BG_RD_LIB_RES
)
if(NOT BG_RD_LIB_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando lib\")
endif()
endif()
message(STATUS \"[BG-RD] ✔ installazione completata\")
message(STATUS \"[BG-RD] =====================================\")
")
endif()
# ======================
# Traduzioni con gettext
@ -1602,14 +2253,14 @@ add_custom_target(translations DEPENDS ${MO_TARGETS})
install(FILES desktop/BastionGuard.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
install(FILES desktop/BastionGuard-bankgui.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
install(FILES desktop/BastionGuard-secure.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
install(FILES desktop/bastionguard-bankopener.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
if(ENABLE_CEF)
install(FILES
desktop/BastionGuard-bankgui.desktop
desktop/BastionGuard-secure.desktop
desktop/bastionguard-bankopener.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications
)
endif()
install(FILES desktop/BastionGuard-autostart.desktop
DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/xdg/autostart)
@ -1719,11 +2370,18 @@ install(FILES actions/policy/org.BastionGuard.policy
DESTINATION /usr/share/polkit-1/actions
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
if(ENABLE_CEF AND ENABLE_SYSTEM_CA_INSTALL)
install(FILES actions/policy/eu.bastionguard.install-ca.policy
DESTINATION /usr/share/polkit-1/actions
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
endif()
install(FILES actions/dbus/org.BastionGuard.USBD.conf
DESTINATION /usr/share/dbus-1/system.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# Install DBus activation service (system bus)
# Install DBus system service
install(
FILES actions/dbus/org.BastionGuard.USBD.service
DESTINATION /usr/share/dbus-1/system-services
@ -1737,11 +2395,41 @@ install(FILES actions/policy/it.BastionGuard.camera.policy
DESTINATION /usr/share/polkit-1/actions
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# ======================
# Permission Policy – Privacy Webcam
# ======================
install(FILES data/sudoers/bastionguard-helper
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# ======================
# Permission Policy – Bank helper
# ======================
if(ENABLE_CEF)
install(FILES data/sudoers/bastionguard-bank
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
endif()
# ======================
# Permission Policy – Helper anti-phishing-update
# ======================
install(FILES data/sudoers/bastionguard-phishing
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
if(ENABLE_CEF)
install(PROGRAMS
data/scripts/bank-helper
DESTINATION /usr/bin/
)
endif()
# ======================
# Services
# ======================
# opzione per abilitare auto attivazione user units durante 'cmake --install' (default OFF)
# opzione per abilitare automaticamente le user units durante 'cmake --install' (default OFF)
option(ENABLE_USER_AGENT_AUTO "Attempt to enable systemd --user unit for logged-in users at install time" OFF)
# install system units (system-wide)
@ -1764,11 +2452,20 @@ install(FILES
data/service/BastionGuard-ransomware-realtime-alert.service
data/service/BastionGuard-ransomware-scanner.service
data/service/BastionGuard-pacd.service
data/service/BastionGuard-cef.service
data/service/BastionGuard-mailproxy.service
data/service/BastionGuard-user-session-watch.service
DESTINATION /usr/lib/systemd/user
)
if(ENABLE_CEF AND ENABLE_CEF_DAEMON)
install(FILES data/service/BastionGuard-cef.service
DESTINATION /usr/lib/systemd/user
)
install(FILES data/service/BastionGuard-cef.service
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data/service
)
endif()
# helper script to enable user agents for logged-in users
@ -1779,9 +2476,16 @@ install(PROGRAMS
data/scripts/BastionGuard-export-env.sh
data/scripts/BastionGuard-locale.sh
data/scripts/BastionGuard-setup-clamav-daemon.sh
data/scripts/BastionGuard-user-session-watch.sh
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data/scripts
)
if(ENABLE_CEF AND ENABLE_SYSTEM_CA_INSTALL)
install(PROGRAMS data/scripts/install-ca-system.sh
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data/scripts
)
endif()
install(PROGRAMS
data/extension/bastionguard-tb-extension/install-tb-extension.sh
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data/extension/bastionguard-tb-extension

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,16 +1,43 @@
#
#
# BastionGuard™
# Copyright (C) 2025–2026 Calogero Scarnà
#
# 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, version 3.
#
# 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, see <https://www.gnu.org/licenses/>.
#
# BastionGuard™ is a trademark of Calogero Scarnà.
# The BastionGuard™ name and branding are not licensed under the GPL.
#
#
# Spec file for BastionGuard (openSUSE Tumbleweed)
#
Name: bastionguard
Version: 1.1
Release: 0
Version: 2.0
Release: 1
Summary: BastionGuard Security Platform
License: GPL-3.0-or-later
URL: https://git.bastionguard.eu/specialworld83/BastionGuard.git
URL: https://git.bastionguard.eu/specialworld83/BastionGuard
Source0: %{name}-%{version}.tar.gz
# Optional deps toggles
Provides: bastionguard = %{version}-%{release}
Obsoletes: bastionguard < %{version}-%{release}
# Disable debuginfo / debugsource packages
%global debug_package %{nil}
%bcond_with hyperscan
BuildRequires: gcc-c++
@ -25,16 +52,17 @@ BuildRequires: gzip
BuildRequires: patch
BuildRequires: findutils
BuildRequires: which
BuildRequires: gettext-tools
# GTK stack
BuildRequires: python311
BuildRequires: pkgconfig(gtk4)
BuildRequires: pkgconfig(gtkmm-4.0)
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(glibmm-2.68)
BuildRequires: pkgconfig(giomm-2.68)
BuildRequires: pkgconfig(pangomm-2.48)
BuildRequires: pkgconfig(sigc++-3.0)
BuildRequires: pkgconfig(libudev)
BuildRequires: pkgconfig(libsoup-3.0)
BuildRequires: pkgconfig(libsecret-1)
@ -54,18 +82,15 @@ BuildRequires: libboost_thread-devel
BuildRequires: pkgconfig(hyperscan)
%endif
# Media / shaping
BuildRequires: pkgconfig(libpng)
BuildRequires: pkgconfig(libjpeg)
BuildRequires: pkgconfig(libtiff-4)
BuildRequires: pkgconfig(libwebp)
BuildRequires: pkgconfig(fribidi)
# NSS/NSPR (if used)
BuildRequires: pkgconfig(nspr)
BuildRequires: pkgconfig(nss)
# X11 / Wayland
BuildRequires: pkgconfig(x11)
BuildRequires: pkgconfig(xcursor)
BuildRequires: pkgconfig(xrandr)
@ -78,28 +103,69 @@ BuildRequires: pkgconfig(xkbcommon)
BuildRequires: pkgconfig(wayland-client)
BuildRequires: pkgconfig(wayland-protocols)
# Audio
BuildRequires: pkgconfig(alsa)
BuildRequires: pkgconfig(libpipewire-0.3)
# SMB client
BuildRequires: samba-devel
# Boost build
BuildRequires: boost-devel
# Vital runtime services (manual)
# bastionguard-backup (fork GTK4 in Vala, build Meson)
BuildRequires: meson
BuildRequires: vala
BuildRequires: pkgconfig(gtk4)
BuildRequires: pkgconfig(gio-unix-2.0)
BuildRequires: pkgconfig(json-glib-1.0)
BuildRequires: pkgconfig(vte-2.91-gtk4)
BuildRequires: pkgconfig(gee-0.8)
BuildRequires: help2man
# bastionguard-secure-connection (Meson + Go)
BuildRequires: go
BuildRequires: protobuf-devel
BuildRequires: grpc-devel
# SC GUI (mappa) + daemon eBPF
BuildRequires: pkgconfig(shumate-1.0)
BuildRequires: libnetfilter_queue-devel
BuildRequires: clang
BuildRequires: libvte-2_91-0
BuildRequires: vte-devel
BuildRequires: typelib-1_0-Vte-2_91
BuildRequires: bubblewrap
BuildRequires: polkit
BuildRequires: nginx
BuildRequires: php8-fpm
BuildRequires: dnsmasq
BuildRequires: clamav
BuildRequires: rsync
BuildRequires: yara
BuildRequires: curl
BuildRequires: mozilla-nss
BuildRequires: mozilla-nss-tools
BuildRequires: sudo
BuildRequires: patchelf
BuildRequires: pkgconfig(libzstd)
BuildRequires: lzo-devel
#BPF Module
BuildRequires: libbpf1
BuildRequires: libbpf-devel
BuildRequires: libbpf-tools
BuildRequires: bpftool
Requires: bubblewrap
Requires: polkit
Requires: nginx
Requires: php8-fpm
Requires: dnsmasq
Requires: clamav
Requires: clamav-daemon
Requires: clamav-freshclam
Requires: rsync
Requires: yara
Requires: curl
Requires: mozilla-nss
Requires: mozilla-nss-tools
Requires: sudo
%description
@ -129,12 +195,10 @@ unset LDFLAGS
%global hyperscan_flag -DENABLE_HYPERSCAN=OFF
%endif
export PKG_CONFIG_PATH="/usr/lib64/pkgconfig:/usr/share/pkgconfig:/usr/lib/pkgconfig:${PKG_CONFIG_PATH}"
%cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=%{_prefix} \
-DCMAKE_INSTALL_SYSCONFDIR=/etc \
-DCMAKE_INSTALL_SYSCONFDIR=%{_sysconfdir} \
-DCMAKE_INSTALL_LOCALSTATEDIR=%{_localstatedir} \
-DCMAKE_INSTALL_DATAROOTDIR=%{_datadir} \
-DBoost_NO_BOOST_CMAKE=ON \
@ -144,33 +208,45 @@ export PKG_CONFIG_PATH="/usr/lib64/pkgconfig:/usr/share/pkgconfig:/usr/lib/pkgco
-DINSTALL_NGINX_DEFAULTS=OFF \
-DBG_PACKAGING=ON \
-DBG_DEBIAN_NO_INSTALL_CODE=ON \
-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
-DCMAKE_INSTALL_RPATH='$ORIGIN/../share/BastionGuard/lib;$ORIGIN/../share/BastionGuard/cef' \
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=OFF \
%{hyperscan_flag}
%cmake_build
%install
%cmake_install
# Sanity checks (fail fast)
install -dm750 %{buildroot}%{_sharedstatedir}/bastionguard-webui/{cache,quarantine,sessions,tmp}
install -dm755 %{buildroot}%{_localstatedir}/log/bastionguard-webui
# Sanity checks
test -x %{buildroot}%{_bindir}/BastionGuard
file %{buildroot}%{_bindir}/BastionGuard | grep -q "ELF"
readelf -d %{buildroot}%{_bindir}/BastionGuard | grep -q NEEDED
%postun
if command -v systemctl >/dev/null 2>&1; then
systemctl daemon-reload >/dev/null 2>&1 || :
fi
:
%files
%{_bindir}/*
%{_datadir}/BastionGuard
%{_datadir}/BastionGuard
%{_datadir}/bastionguard-backup
%{_datadir}/bastionguard-sc
%{_datadir}/applications/BastionGuard.desktop
%{_datadir}/applications/BastionGuard-bankgui.desktop
%{_datadir}/applications/BastionGuard-secure.desktop
%{_datadir}/applications/bastionguard-bankopener.desktop
%{_datadir}/applications/bastionguard-sc.desktop
%{_datadir}/applications/bastionguard-backup-gtk.desktop
%config(noreplace) %{_sysconfdir}/xdg/autostart/BastionGuard-autostart.desktop
%config(noreplace) %{_sysconfdir}/xdg/autostart/bastionguard-sc-autostart.desktop
%{_datadir}/dbus-1/services/org.BastionGuard.RansomwareAlert.service
%{_datadir}/dbus-1/system-services/org.BastionGuard.USBD.service
@ -180,15 +256,47 @@ readelf -d %{buildroot}%{_bindir}/BastionGuard | grep -q NEEDED
%{_datadir}/polkit-1/actions/org.BastionGuard.policy
%{_datadir}/polkit-1/actions/org.BastionGuard.ransomware.policy
%{_datadir}/polkit-1/actions/org.BastionGuard.USBD.policy
%{_datadir}/polkit-1/actions/eu.bastionguard.install-ca.policy
%{_datadir}/polkit-1/actions/eu.bastionguard.sc.policy
%{_datadir}/polkit-1/actions/org.bastionguard.pkexec.backup.policy
%{_unitdir}/*
%{_userunitdir}/*
/usr/share/locale/*
/usr/share/icons/*
/usr/share/plymouth/*
/etc/bastionguard-backup/*
/usr/lib/bastionguard-sc/*
/usr/share/metainfo/*
/usr/share/man/*
/usr/share/icons/hicolor/*/apps/*
%dir %{_libexecdir}/bastionguard
%{_libexecdir}/bastionguard/archive_worker
%config(noreplace) %{_sysconfdir}/sudoers.d/bastionguard-helper
%config(noreplace) %{_sysconfdir}/sudoers.d/bastionguard-bank
%config(noreplace) %{_sysconfdir}/sudoers.d/bastionguard-phishing
%dir %attr(750,apache,apache) %{_sharedstatedir}/bastionguard-webui
%dir %attr(750,apache,apache) %{_sharedstatedir}/bastionguard-webui/cache
%dir %attr(750,apache,apache) %{_sharedstatedir}/bastionguard-webui/quarantine
%dir %attr(750,apache,apache) %{_sharedstatedir}/bastionguard-webui/sessions
%dir %attr(750,apache,apache) %{_sharedstatedir}/bastionguard-webui/tmp
%dir %attr(755,root,root) %{_localstatedir}/log/bastionguard-webui
# ── BastionGuard Recovery Data ──────────────────────────────
%{_datadir}/bastionguard-recovery-data
%{_datadir}/applications/com.bastionguard.RecoveryData.desktop
%{_datadir}/polkit-1/actions/com.bastionguard.RecoveryData.policy
%{_datadir}/locale/*/LC_MESSAGES/bastionguard-recovery-data.mo
# ── Plymouth theme ──────────────────────────────────────────
%{_datadir}/plymouth/themes/bastionguard
%{_datadir}/pixmaps/*
# ── BastionGuard Secure Connection: config daemon ───────────
%dir %{_sysconfdir}/bastionguard-secure-connectiond
%config(noreplace) %{_sysconfdir}/bastionguard-secure-connectiond/*
%changelog
* Fri Mar 13 2026 Calogero Scarnà <info@bastionguard.eu> - 1.1-1
- Update package, view changelog
* Fri Jun 12 2026 Calogero Scarnà <info@bastionguard.eu> - 2.0
- Update package

View file

@ -160,6 +160,19 @@ function(bg_link_systemd tgt)
target_compile_options(${tgt} PRIVATE ${SYSTEMD_CFLAGS_OTHER})
endif()
endfunction()
# ======================
# libsystemd / sd-bus
# ======================
pkg_check_modules(SYSTEMD REQUIRED libsystemd)
if (SYSTEMD_FOUND)
message(STATUS "✔ libsystemd trovato: ${SYSTEMD_VERSION}")
include_directories(${SYSTEMD_INCLUDE_DIRS})
link_directories(${SYSTEMD_LIBRARY_DIRS})
add_definitions(${SYSTEMD_CFLAGS_OTHER})
else()
message(FATAL_ERROR "❌ libsystemd non trovato. Installa libsystemd-dev")
endif()
# ==============================
# Controllo NGINX
# ==============================
@ -466,6 +479,36 @@ target_link_libraries(identity_leak
nlohmann_json::nlohmann_json
)
# ======================
# Password Manager Module
# ======================
set(PASSWORD_MANAGER_SOURCES
src/password_manager/PasswordEntry.cpp
src/password_manager/PasswordVault.cpp
src/password_manager/PasswordGenerator.cpp
src/password_manager/PasswordDialogs.cpp
src/password_manager/PasswordSearchRow.cpp
src/password_manager/PasswordManagerPage.cpp
src/password_manager/PasswordImporter.cpp
src/password_manager/PasswordImportDialog.cpp
src/password_manager/PasswordVaultView.cpp
)
add_library(password_manager STATIC ${PASSWORD_MANAGER_SOURCES})
target_include_directories(password_manager PUBLIC
src
src/password_manager
)
target_link_libraries(password_manager
PUBLIC
${GTKMM_LIBRARIES}
${GIOMM_LIBRARIES}
${SIGC_LIBRARIES}
${LIBSECRET_LIBRARIES}
nlohmann_json::nlohmann_json
)
# ======================
# RE2 (opzionale, per regex sicure e veloci)
@ -556,6 +599,11 @@ set(BastionGuard_SOURCES
src/usb/LiveScanDialog.cpp
src/phishing_search/PhishingPage.cpp
src/phishing_search/PhishingCheckCard.cpp
src/vpn/VpnPage.cpp
src/vpn/WireguardBackend.cpp
src/password_manager/PasswordManagerPage.cpp
src/backup/BackupPage.cpp
src/Utils.cpp
)
add_executable(BastionGuard ${BastionGuard_SOURCES})
target_include_directories(BastionGuard
@ -565,8 +613,8 @@ target_include_directories(BastionGuard
)
target_compile_definitions(BastionGuard PRIVATE
BASTIONGUARD_VERSION="1.1"
BASTIONGUARD_BUILD=20260310
BASTIONGUARD_VERSION="2.0"
BASTIONGUARD_BUILD=20260411
)
target_link_libraries(BastionGuard
@ -583,10 +631,12 @@ target_link_libraries(BastionGuard
phishing_common
firewall
identity_leak
password_manager
CURL::libcurl
OpenSSL::SSL
OpenSSL::Crypto
)
target_link_options(BastionGuard PRIVATE -lsystemd)
bg_set_rpath(BastionGuard)
bg_link_systemd(BastionGuard)
# ============================================================
@ -794,6 +844,7 @@ set(RANSW_ALERT_SOURCES
src/AntiRansomEngine.cpp
src/AntiPhishingEngine.cpp
src/Quarantine.cpp
src/Utils.cpp
)
add_executable(BastionGuard-ransomware-alert ${RANSW_ALERT_SOURCES})
@ -830,6 +881,7 @@ set(RANSW_REALTIME_ALERT_SOURCES
src/AntiRansomEngine.cpp
src/AntiPhishingEngine.cpp
src/Quarantine.cpp
src/Utils.cpp
)
add_executable(BastionGuard-ransomware-realtime-alert ${RANSW_REALTIME_ALERT_SOURCES})
@ -1018,6 +1070,7 @@ set(WIZARD_SOURCES
src/wizard/wizard_setup.cpp
src/wizard/main.cpp
src/wizard/StyleProvider.cpp
src/Utils.cpp
)
add_executable(BastionGuard-wizard ${WIZARD_SOURCES})
@ -1354,13 +1407,13 @@ target_link_libraries(bastionguard-cef
PRIVATE
${BG_BOOST_HEADERS}
Threads::Threads
OpenSSL::SSL
OpenSSL::Crypto
${GTKMM_LIBRARIES}
${GIOMM_LIBRARIES}
${SIGC_LIBRARIES}
${SOUP_LIBRARIES}
${GLIB_LIBRARIES}
${CEF_LIB}
${CEF_WRAPPER}
@ -1453,6 +1506,7 @@ install(TARGETS BastionGuard-secure RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# ---- GUI selector ----
add_executable(BastionGuard-secure-gui
src/payment_secure/BastionGuard-secure-main.cpp
src/payment_secure/dns_secure.cpp
src/StyleProvider.cpp
)
@ -1530,6 +1584,497 @@ install(FILES
)
# ============================================================
# BastionGuard WebUI
# ============================================================
set(BG_WEBUI_SOURCE_DIR "${CMAKE_SOURCE_DIR}/webui")
set(BG_WEBUI_BUILD_DIR "${CMAKE_BINARY_DIR}/webui")
set(BG_WEBUI_STAMP "${BG_WEBUI_BUILD_DIR}/.webui-staged")
if(EXISTS "${BG_WEBUI_SOURCE_DIR}/index.php")
add_custom_command(
OUTPUT "${BG_WEBUI_STAMP}"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${BG_WEBUI_SOURCE_DIR}"
"${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E touch "${BG_WEBUI_STAMP}"
DEPENDS "${BG_WEBUI_SOURCE_DIR}/index.php"
COMMENT "Staging BastionGuard WebUI into the build directory"
VERBATIM
)
add_custom_target(BastionGuard-webui ALL
DEPENDS "${BG_WEBUI_STAMP}"
)
install(DIRECTORY "${BG_WEBUI_BUILD_DIR}/"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/webui"
USE_SOURCE_PERMISSIONS
COMPONENT webui
PATTERN ".git" EXCLUDE
PATTERN "*.bak" EXCLUDE
PATTERN "*.tmp" EXCLUDE
PATTERN ".webui-staged" EXCLUDE
)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/data/vhosts/webui/"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data/vhosts/webui"
USE_SOURCE_PERMISSIONS
COMPONENT webui
OPTIONAL
)
install(CODE "
message(STATUS \"[WebUI] Installed in: ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/webui\")
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/cache)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/quarantine)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/sessions)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/tmp)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/log/bastionguard-webui)
")
else()
message(WARNING "BastionGuard WebUI source not found at ${BG_WEBUI_SOURCE_DIR}; WebUI will not be installed.")
endif()
# ======================
# BastionGuard Backup (fork di Timeshift, build via Meson)
# ======================
option(ENABLE_BASTIONGUARD_BACKUP "Build bastionguard-backup (Timeshift fork)" ON)
if(ENABLE_BASTIONGUARD_BACKUP)
include(ExternalProject)
find_program(MESON_EXECUTABLE meson REQUIRED)
find_program(NINJA_EXECUTABLE ninja REQUIRED)
find_program(VALAC_EXECUTABLE valac REQUIRED)
find_program(PKG_CONFIG_EXECUTABLE pkg-config REQUIRED)
# Dipendenze runtime/build del fork
pkg_check_modules(BG_BACKUP_GTK3 REQUIRED gtk+-3.0)
pkg_check_modules(BG_BACKUP_GIO REQUIRED gio-2.0 gio-unix-2.0)
pkg_check_modules(BG_BACKUP_JSON REQUIRED json-glib-1.0)
pkg_check_modules(BG_BACKUP_VTE REQUIRED vte-2.91)
pkg_check_modules(BG_BACKUP_GEE REQUIRED gee-0.8)
set(BG_BACKUP_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-backup")
set(BG_BACKUP_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-backup-build")
set(BG_BACKUP_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-backup-install")
message(STATUS "[BG-Backup] Source dir : ${BG_BACKUP_SOURCE_DIR}")
message(STATUS "[BG-Backup] Build dir : ${BG_BACKUP_BINARY_DIR}")
message(STATUS "[BG-Backup] Stage dir : ${BG_BACKUP_INSTALL_DIR}")
message(STATUS "[BG-Backup] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_backup_ext
SOURCE_DIR "${BG_BACKUP_SOURCE_DIR}"
BINARY_DIR "${BG_BACKUP_BINARY_DIR}"
CONFIGURE_COMMAND
${MESON_EXECUTABLE} setup "${BG_BACKUP_BINARY_DIR}" "${BG_BACKUP_SOURCE_DIR}"
--prefix=/usr
--buildtype=release
--reconfigure
BUILD_COMMAND
${MESON_EXECUTABLE} compile -C "${BG_BACKUP_BINARY_DIR}"
INSTALL_COMMAND
${MESON_EXECUTABLE} install -C "${BG_BACKUP_BINARY_DIR}" --destdir "${BG_BACKUP_INSTALL_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-backup ALL
DEPENDS bastionguard_backup_ext
)
install(CODE "
set(BG_BACKUP_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-Backup] =====================================\")
message(STATUS \"[BG-Backup] Installazione bastionguard-backup\")
message(STATUS \"[BG-Backup] Stage dir Meson : ${BG_BACKUP_INSTALL_DIR}\")
message(STATUS \"[BG-Backup] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-Backup] DESTDIR : \${BG_BACKUP_DESTDIR}\")
message(STATUS \"[BG-Backup]\")
set(BG_BACKUP_STAGE_BIN \"${BG_BACKUP_INSTALL_DIR}/usr/bin\")
set(BG_BACKUP_STAGE_SHARE \"${BG_BACKUP_INSTALL_DIR}/usr/share\")
set(BG_BACKUP_STAGE_ETC \"${BG_BACKUP_INSTALL_DIR}/etc\")
set(BG_BACKUP_DEST_BIN \"\${BG_BACKUP_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_BACKUP_DEST_SHARE \"\${BG_BACKUP_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_BACKUP_DEST_ETC \"\${BG_BACKUP_DESTDIR}/etc\")
message(STATUS \"[BG-Backup] Copia binari : \${BG_BACKUP_STAGE_BIN} -> \${BG_BACKUP_DEST_BIN}\")
if(EXISTS \"\${BG_BACKUP_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_BIN}\"
\"\${BG_BACKUP_DEST_BIN}\"
RESULT_VARIABLE BG_BACKUP_BIN_RES
)
if(NOT BG_BACKUP_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando i binari in \${BG_BACKUP_DEST_BIN}\")
endif()
else()
message(WARNING \"[BG-Backup] Directory bin non trovata: \${BG_BACKUP_STAGE_BIN}\")
endif()
message(STATUS \"[BG-Backup] Copia share : \${BG_BACKUP_STAGE_SHARE} -> \${BG_BACKUP_DEST_SHARE}\")
if(EXISTS \"\${BG_BACKUP_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_SHARE}\"
\"\${BG_BACKUP_DEST_SHARE}\"
RESULT_VARIABLE BG_BACKUP_SHARE_RES
)
if(NOT BG_BACKUP_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando share in \${BG_BACKUP_DEST_SHARE}\")
endif()
else()
message(WARNING \"[BG-Backup] Directory share non trovata: \${BG_BACKUP_STAGE_SHARE}\")
endif()
message(STATUS \"[BG-Backup] Copia etc : \${BG_BACKUP_STAGE_ETC} -> \${BG_BACKUP_DEST_ETC}\")
if(EXISTS \"\${BG_BACKUP_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_ETC}\"
\"\${BG_BACKUP_DEST_ETC}\"
RESULT_VARIABLE BG_BACKUP_ETC_RES
)
if(NOT BG_BACKUP_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando etc in \${BG_BACKUP_DEST_ETC}\")
endif()
else()
message(STATUS \"[BG-Backup] Nessuna directory etc da installare\")
endif()
message(STATUS \"[BG-Backup] ✔ installazione completata\")
message(STATUS \"[BG-Backup] =====================================\")
")
endif()
# ======================
# BastionGuard Secure Connection (Meson + Go)
# ======================
option(ENABLE_BASTIONGUARD_SECURE_CONNECTION "Build bastionguard-secure-connection" ON)
if(ENABLE_BASTIONGUARD_SECURE_CONNECTION)
include(ExternalProject)
find_program(MESON_EXECUTABLE meson REQUIRED)
find_program(NINJA_EXECUTABLE ninja REQUIRED)
find_program(GO_EXECUTABLE go REQUIRED)
find_program(PROTOC_EXECUTABLE protoc REQUIRED)
find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin REQUIRED)
find_program(PKG_CONFIG_EXECUTABLE pkg-config REQUIRED)
set(BG_SC_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-secure-connection")
set(BG_SC_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-secure-connection-build")
set(BG_SC_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-secure-connection-install")
message(STATUS "[BG-SC] Source dir : ${BG_SC_SOURCE_DIR}")
message(STATUS "[BG-SC] Build dir : ${BG_SC_BINARY_DIR}")
message(STATUS "[BG-SC] Stage dir : ${BG_SC_INSTALL_DIR}")
message(STATUS "[BG-SC] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_secure_connection_ext
SOURCE_DIR "${BG_SC_SOURCE_DIR}"
BINARY_DIR "${BG_SC_BINARY_DIR}"
CONFIGURE_COMMAND
${MESON_EXECUTABLE} setup "${BG_SC_BINARY_DIR}" "${BG_SC_SOURCE_DIR}"
--prefix=/usr
--sysconfdir=/etc
--localedir=share/locale
--buildtype=release
--reconfigure
BUILD_COMMAND
${MESON_EXECUTABLE} compile -C "${BG_SC_BINARY_DIR}"
INSTALL_COMMAND
${MESON_EXECUTABLE} install -C "${BG_SC_BINARY_DIR}" --destdir "${BG_SC_INSTALL_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-secure-connection ALL
DEPENDS bastionguard_secure_connection_ext
)
install(CODE "
set(BG_SC_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-SC] =====================================\")
message(STATUS \"[BG-SC] Installazione bastionguard-secure-connection\")
message(STATUS \"[BG-SC] Stage dir Meson : ${BG_SC_INSTALL_DIR}\")
message(STATUS \"[BG-SC] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-SC] DESTDIR : \${BG_SC_DESTDIR}\")
set(BG_SC_STAGE_BIN \"${BG_SC_INSTALL_DIR}/usr/bin\")
set(BG_SC_STAGE_SHARE \"${BG_SC_INSTALL_DIR}/usr/share\")
set(BG_SC_STAGE_ETC \"${BG_SC_INSTALL_DIR}/etc\")
set(BG_SC_STAGE_LIB \"${BG_SC_INSTALL_DIR}/usr/lib\")
set(BG_SC_DEST_BIN \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_SC_DEST_SHARE \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_SC_DEST_ETC \"\${BG_SC_DESTDIR}/etc\")
set(BG_SC_DEST_LIB \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/lib\")
if(EXISTS \"\${BG_SC_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_BIN}\"
\"\${BG_SC_DEST_BIN}\"
RESULT_VARIABLE BG_SC_BIN_RES
)
if(NOT BG_SC_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando i binari\")
endif()
endif()
if(EXISTS \"\${BG_SC_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_SHARE}\"
\"\${BG_SC_DEST_SHARE}\"
RESULT_VARIABLE BG_SC_SHARE_RES
)
if(NOT BG_SC_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando share\")
endif()
endif()
if(EXISTS \"\${BG_SC_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_ETC}\"
\"\${BG_SC_DEST_ETC}\"
RESULT_VARIABLE BG_SC_ETC_RES
)
if(NOT BG_SC_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando etc\")
endif()
endif()
# ── Copia esplicita config daemon in /etc/bastionguard-secure-connectiond ──
# Meson installa i JSON con sysconfdir=/etc (assoluto), quindi nella stage
# finiscono sempre in <INSTALL_DIR>/etc/bastionguard-secure-connectiond/.
# Con DESTDIR finiscono dentro il pkgdir, senza DESTDIR in /etc di sistema.
set(BG_SC_CONF_SRC \"${BG_SC_INSTALL_DIR}/etc/bastionguard-secure-connectiond\")
set(BG_SC_CONF_DST \"\${BG_SC_DESTDIR}/etc/bastionguard-secure-connectiond\")
if(EXISTS \"\${BG_SC_CONF_SRC}\")
file(MAKE_DIRECTORY \"\${BG_SC_CONF_DST}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_CONF_SRC}\"
\"\${BG_SC_CONF_DST}\"
RESULT_VARIABLE BG_SC_CONF_RES
)
if(NOT BG_SC_CONF_RES EQUAL 0)
message(WARNING \"[BG-SC] Impossibile copiare la config (permessi?): \${BG_SC_CONF_DST}\")
else()
message(STATUS \"[BG-SC] ✔ Config daemon installata: \${BG_SC_CONF_DST}\")
endif()
else()
message(WARNING \"[BG-SC] Directory config non trovata nella stage: \${BG_SC_CONF_SRC}\")
endif()
# ── Copia esplicita autostart in /etc/xdg/autostart ──────────────────
set(BG_SC_AUTOSTART_SRC
\"${BG_SC_INSTALL_DIR}/etc/xdg/autostart/bastionguard-sc-autostart.desktop\")
set(BG_SC_AUTOSTART_DST \"\${BG_SC_DESTDIR}/etc/xdg/autostart/bastionguard-sc-autostart.desktop\")
if(EXISTS \"\${BG_SC_AUTOSTART_SRC}\")
file(MAKE_DIRECTORY \"\${BG_SC_DESTDIR}/etc/xdg/autostart\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy
\"\${BG_SC_AUTOSTART_SRC}\"
\"\${BG_SC_AUTOSTART_DST}\"
RESULT_VARIABLE BG_SC_AUTOSTART_RES
)
if(NOT BG_SC_AUTOSTART_RES EQUAL 0)
message(WARNING \"[BG-SC] Impossibile copiare l'autostart (permessi?): \${BG_SC_AUTOSTART_DST}\")
else()
message(STATUS \"[BG-SC] ✔ Autostart installato: \${BG_SC_AUTOSTART_DST}\")
endif()
else()
message(WARNING \"[BG-SC] File autostart non trovato nella stage: \${BG_SC_AUTOSTART_SRC}\")
endif()
if(EXISTS \"\${BG_SC_STAGE_LIB}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_LIB}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_LIB}\"
\"\${BG_SC_DEST_LIB}\"
RESULT_VARIABLE BG_SC_LIB_RES
)
if(NOT BG_SC_LIB_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando lib\")
endif()
endif()
message(STATUS \"[BG-SC] ✔ installazione completata\")
message(STATUS \"[BG-SC] =====================================\")
")
endif()
# ======================
# BastionGuard Recovery Data (CMake)
# ======================
option(ENABLE_BASTIONGUARD_RECOVERY_DATA "Build bastionguard-recovery-data" ON)
if(ENABLE_BASTIONGUARD_RECOVERY_DATA)
include(ExternalProject)
set(BG_RD_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-recovery-data")
set(BG_RD_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-recovery-data-build")
set(BG_RD_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-recovery-data-install")
message(STATUS "[BG-RD] Source dir : ${BG_RD_SOURCE_DIR}")
message(STATUS "[BG-RD] Build dir : ${BG_RD_BINARY_DIR}")
message(STATUS "[BG-RD] Stage dir : ${BG_RD_INSTALL_DIR}")
message(STATUS "[BG-RD] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_recovery_data_ext
SOURCE_DIR "${BG_RD_SOURCE_DIR}"
BINARY_DIR "${BG_RD_BINARY_DIR}"
CONFIGURE_COMMAND
"${CMAKE_COMMAND}" -S "${BG_RD_SOURCE_DIR}" -B "${BG_RD_BINARY_DIR}"
-DCMAKE_INSTALL_PREFIX=/usr
-DCMAKE_BUILD_TYPE=Release
BUILD_COMMAND
"${CMAKE_COMMAND}" --build "${BG_RD_BINARY_DIR}" --parallel
INSTALL_COMMAND
"${CMAKE_COMMAND}" -E env DESTDIR=${BG_RD_INSTALL_DIR}
"${CMAKE_COMMAND}" --install "${BG_RD_BINARY_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-recovery-data ALL
DEPENDS bastionguard_recovery_data_ext
)
install(CODE "
set(BG_RD_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-RD] =====================================\")
message(STATUS \"[BG-RD] Installazione bastionguard-recovery-data\")
message(STATUS \"[BG-RD] Stage dir CMake : ${BG_RD_INSTALL_DIR}\")
message(STATUS \"[BG-RD] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-RD] DESTDIR : \${BG_RD_DESTDIR}\")
set(BG_RD_STAGE_BIN \"${BG_RD_INSTALL_DIR}/usr/bin\")
set(BG_RD_STAGE_SHARE \"${BG_RD_INSTALL_DIR}/usr/share\")
set(BG_RD_STAGE_ETC \"${BG_RD_INSTALL_DIR}/etc\")
set(BG_RD_STAGE_LIB \"${BG_RD_INSTALL_DIR}/usr/lib\")
set(BG_RD_DEST_BIN \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_RD_DEST_SHARE \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_RD_DEST_ETC \"\${BG_RD_DESTDIR}/etc\")
set(BG_RD_DEST_LIB \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/lib\")
if(EXISTS \"\${BG_RD_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_BIN}\"
\"\${BG_RD_DEST_BIN}\"
RESULT_VARIABLE BG_RD_BIN_RES
)
if(NOT BG_RD_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando i binari\")
endif()
else()
message(WARNING \"[BG-RD] Directory bin non trovata: \${BG_RD_STAGE_BIN}\")
endif()
if(EXISTS \"\${BG_RD_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_SHARE}\"
\"\${BG_RD_DEST_SHARE}\"
RESULT_VARIABLE BG_RD_SHARE_RES
)
if(NOT BG_RD_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando share\")
endif()
else()
message(WARNING \"[BG-RD] Directory share non trovata: \${BG_RD_STAGE_SHARE}\")
endif()
if(EXISTS \"\${BG_RD_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_ETC}\"
\"\${BG_RD_DEST_ETC}\"
RESULT_VARIABLE BG_RD_ETC_RES
)
if(NOT BG_RD_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando etc\")
endif()
else()
message(STATUS \"[BG-RD] Nessuna directory etc da installare\")
endif()
if(EXISTS \"\${BG_RD_STAGE_LIB}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_LIB}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_LIB}\"
\"\${BG_RD_DEST_LIB}\"
RESULT_VARIABLE BG_RD_LIB_RES
)
if(NOT BG_RD_LIB_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando lib\")
endif()
endif()
message(STATUS \"[BG-RD] ✔ installazione completata\")
message(STATUS \"[BG-RD] =====================================\")
")
endif()
# ======================
# Traduzioni con gettext
# ======================
@ -1712,6 +2257,7 @@ install(FILES data/service/org.BastionGuard.RansomwareAlert.service
install(FILES actions/policy/org.BastionGuard.policy
FILES actions/policy/org.BastionGuard.ransomware.policy
FILES actions/policy/org.BastionGuard.USBD.policy
FILES actions/policy/eu.bastionguard.install-ca.policy
DESTINATION /usr/share/polkit-1/actions
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
@ -1719,7 +2265,7 @@ install(FILES actions/dbus/org.BastionGuard.USBD.conf
DESTINATION /usr/share/dbus-1/system.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# Install DBus activation service (system bus)
# Install DBus system service
install(
FILES actions/dbus/org.BastionGuard.USBD.service
DESTINATION /usr/share/dbus-1/system-services
@ -1733,11 +2279,37 @@ install(FILES actions/policy/it.BastionGuard.camera.policy
DESTINATION /usr/share/polkit-1/actions
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# ======================
# Permission Policy – Privacy Webcam
# ======================
install(FILES data/sudoers/bastionguard-helper
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# ======================
# Permission Policy – Bank helper
# ======================
install(FILES data/sudoers/bastionguard-bank
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# ======================
# Permission Policy – Helper anti-phishing-update
# ======================
install(FILES data/sudoers/bastionguard-phishing
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
install(PROGRAMS
data/scripts/bank-helper
DESTINATION /usr/bin/
)
# ======================
# Services
# ======================
# opzione per abilitare auto attivazione user units durante 'cmake --install' (default OFF)
# opzione per abilitare automaticamente le user units durante 'cmake --install' (default OFF)
option(ENABLE_USER_AGENT_AUTO "Attempt to enable systemd --user unit for logged-in users at install time" OFF)
# install system units (system-wide)
@ -1762,6 +2334,7 @@ install(FILES
data/service/BastionGuard-pacd.service
data/service/BastionGuard-cef.service
data/service/BastionGuard-mailproxy.service
data/service/BastionGuard-user-session-watch.service
DESTINATION /usr/lib/systemd/user
)
@ -1775,6 +2348,7 @@ install(PROGRAMS
data/scripts/BastionGuard-export-env.sh
data/scripts/BastionGuard-locale.sh
data/scripts/BastionGuard-setup-clamav-daemon.sh
data/scripts/BastionGuard-user-session-watch.sh
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data/scripts
)

View file

@ -1,51 +1,65 @@
#
# BastionGuard™
# Copyright (C) 2025–2026 Calogero Scarnà
#
# 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, version 3.
#
# 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, see <https://www.gnu.org/licenses/>.
#
# BastionGuard™ is a trademark of Calogero Scarnà.
# The BastionGuard™ name and branding are not licensed under the GPL.
#
# Maintainer: BastionGuard info@bastionguard.eu
pkgname=bastionguard
pkgver=1.1
pkgver=2.0
pkgrel=1
pkgdesc="Transparent security control plane for Linux desktops
BastionGuard is not a trust us security product.
It is a security control plane for Linux desktops where every protection
mechanism is explicit, deterministic, and observable.
Unlike most desktop security tools, which hide decisions behind opaque
engines, cloud scoring, or silent automation, BastionGuard exposes
what is happening, why it is happening, and how protections are applied.
Users and administrators can see, control, and reason about every
security decision."
pkgdesc="BastionGuard - transparent security control plane for Linux desktops (donate edition)"
arch=('x86_64')
url="https://bastionguard.eu/"
license=('GPL3')
depends=(
'glibc' 'gcc-libs'
# GUI toolkit (gtkmm-4.0 stack)
'gtkmm-4.0' 'gtk4' 'glib2' 'glibmm' 'pangomm-2.48' 'pango' 'cairomm' 'cairo'
'harfbuzz' 'gdk-pixbuf2' 'graphene' 'libsigc++' 'boost' 'libxcomposite'
'libsoup3' 'libsecret' 'curl' 'openssl' 'sqlite' 'libidn2' 're2' 'yara' 'polkit'
'systemd-libs' 'samba'
'libglvnd' 'vulkan-icd-loader'
'boost-libs' 'nlohmann-json'
'harfbuzz' 'gdk-pixbuf2' 'graphene' 'libsigc++-3.0'
# Core libraries used by the CMake targets
'boost-libs' 'boost' 'libsoup3' 'libsecret' 'curl' 'openssl' 'sqlite' 'libidn2'
're2' 'yara' 'polkit' 'systemd-libs' 'smbclient' 'nlohmann-json' 'sudo'
# CEF / Chromium runtime dependencies
'nss' 'nspr' 'libglvnd' 'vulkan-icd-loader' 'mesa' 'libdrm'
'alsa-lib' 'dbus' 'at-spi2-core'
'libxcomposite' 'libxdamage' 'libxrandr' 'libxfixes' 'libxkbcommon'
# Runtime bastionguard-backup (fork GTK4) + secure-connection
'vte4' 'vte3' 'libgee' 'json-glib' 'grpc' 'protobuf'
'libshumate' 'libnetfilter_queue' 'libbpf' 'help2man' 'libbpf' 'bcc-libbpf-tools' 'bpf' 'zstd' 'lzo'
# Runtime services / helpers
'nginx' 'php' 'clamav' 'dnsmasq' 'bubblewrap' 'rsync'
)
makedepends=(
'cmake' 'pkgconf' 'gettext' 'python'
'meson' 'ninja' 'mm-common' 'cargo-c'
'meson' 'ninja' 'mm-common' 'cargo-c' 'hyperscan'
# bastionguard-backup (Vala/Meson) + secure-connection (Meson, eBPF)
'vala' 'go' 'clang'
)
options=('strip')
provides=('bastionguard')
conflicts=('bastionguard')
source=("git+https://git.bastionguard.eu/specialworld83/BastionGuard.git")
# Sorgente locale (creata dalla CI come BastionGuard-ci.tar.gz)
source=("BastionGuard-ci.tar.gz")
sha256sums=('SKIP')
pkgver() {
cd "$srcdir/$_srcname"
printf "0.r%s.g%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short=7 HEAD)"
}
_srcname="BastionGuard-ci"
build() {
cd "$srcdir/$_srcname"
@ -60,11 +74,12 @@ build() {
-DENABLE_USER_AGENT_AUTO=OFF \
-DINSTALL_NGINX_DEFAULTS=OFF
cmake --build build -- -j"$(nproc)"
cmake --build build -- -j1
}
package() {
cd "$srcdir/$_srcname"
DESTDIR="$pkgdir" cmake --install build
install -dm750 "$pkgdir"/var/lib/bastionguard-webui/{cache,quarantine,sessions,tmp}
install -dm755 "$pkgdir/var/log/bastionguard-webui"
}

View file

@ -140,7 +140,19 @@ function(bg_set_rpath target)
endif()
endif()
endfunction()
# ======================
# libsystemd / sd-bus
# ======================
pkg_check_modules(SYSTEMD REQUIRED libsystemd)
if (SYSTEMD_FOUND)
message(STATUS "✔ libsystemd trovato: ${SYSTEMD_VERSION}")
include_directories(${SYSTEMD_INCLUDE_DIRS})
link_directories(${SYSTEMD_LIBRARY_DIRS})
add_definitions(${SYSTEMD_CFLAGS_OTHER})
else()
message(FATAL_ERROR "❌ libsystemd non trovato. Installa libsystemd-dev")
endif()
# ==============================
# Controllo NGINX
# ==============================
@ -466,6 +478,36 @@ target_link_libraries(identity_leak
nlohmann_json::nlohmann_json
)
# ======================
# Password Manager Module
# ======================
set(PASSWORD_MANAGER_SOURCES
src/password_manager/PasswordEntry.cpp
src/password_manager/PasswordVault.cpp
src/password_manager/PasswordGenerator.cpp
src/password_manager/PasswordDialogs.cpp
src/password_manager/PasswordSearchRow.cpp
src/password_manager/PasswordManagerPage.cpp
src/password_manager/PasswordImporter.cpp
src/password_manager/PasswordImportDialog.cpp
src/password_manager/PasswordVaultView.cpp
)
add_library(password_manager STATIC ${PASSWORD_MANAGER_SOURCES})
target_include_directories(password_manager PUBLIC
src
src/password_manager
)
target_link_libraries(password_manager
PUBLIC
${GTKMM_LIBRARIES}
${GIOMM_LIBRARIES}
${SIGC_LIBRARIES}
${LIBSECRET_LIBRARIES}
nlohmann_json::nlohmann_json
)
# ======================
# RE2 (opzionale, per regex sicure e veloci)
@ -556,6 +598,11 @@ set(BastionGuard_SOURCES
src/usb/LiveScanDialog.cpp
src/phishing_search/PhishingPage.cpp
src/phishing_search/PhishingCheckCard.cpp
src/vpn/VpnPage.cpp
src/vpn/WireguardBackend.cpp
src/password_manager/PasswordManagerPage.cpp
src/backup/BackupPage.cpp
src/Utils.cpp
)
# === Eseguibile principale ===
@ -567,8 +614,8 @@ target_include_directories(BastionGuard
)
target_compile_definitions(BastionGuard PRIVATE
BASTIONGUARD_VERSION="1.1"
BASTIONGUARD_BUILD=20260310
BASTIONGUARD_VERSION="2.0"
BASTIONGUARD_BUILD=20260411
)
target_link_libraries(BastionGuard
@ -585,10 +632,12 @@ target_link_libraries(BastionGuard
phishing_common
firewall
identity_leak
password_manager
CURL::libcurl
OpenSSL::SSL
OpenSSL::Crypto
)
target_link_options(BastionGuard PRIVATE -lsystemd)
bg_set_rpath(BastionGuard)
bg_link_systemd(BastionGuard)
# ============================================================
@ -821,6 +870,7 @@ set(RANSW_ALERT_SOURCES
src/AntiRansomEngine.cpp
src/AntiPhishingEngine.cpp
src/Quarantine.cpp
src/Utils.cpp
)
add_executable(BastionGuard-ransomware-alert ${RANSW_ALERT_SOURCES})
@ -857,6 +907,7 @@ set(RANSW_REALTIME_ALERT_SOURCES
src/AntiRansomEngine.cpp
src/AntiPhishingEngine.cpp
src/Quarantine.cpp
src/Utils.cpp
)
add_executable(BastionGuard-ransomware-realtime-alert ${RANSW_REALTIME_ALERT_SOURCES})
@ -1045,6 +1096,7 @@ set(WIZARD_SOURCES
src/wizard/wizard_setup.cpp
src/wizard/main.cpp
src/wizard/StyleProvider.cpp
src/Utils.cpp
)
add_executable(BastionGuard-wizard ${WIZARD_SOURCES})
@ -1383,13 +1435,13 @@ target_link_libraries(bastionguard-cef
PRIVATE
${BG_BOOST_HEADERS}
Threads::Threads
OpenSSL::SSL
OpenSSL::Crypto
${GTKMM_LIBRARIES}
${GIOMM_LIBRARIES}
${SIGC_LIBRARIES}
${SOUP_LIBRARIES}
${GLIB_LIBRARIES}
${CEF_LIB}
${CEF_WRAPPER}
@ -1482,6 +1534,7 @@ install(TARGETS BastionGuard-secure RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# ---- GUI selector ----
add_executable(BastionGuard-secure-gui
src/payment_secure/BastionGuard-secure-main.cpp
src/payment_secure/dns_secure.cpp
src/StyleProvider.cpp
)
@ -1559,6 +1612,497 @@ install(FILES
)
# ============================================================
# BastionGuard WebUI
# ============================================================
set(BG_WEBUI_SOURCE_DIR "${CMAKE_SOURCE_DIR}/webui")
set(BG_WEBUI_BUILD_DIR "${CMAKE_BINARY_DIR}/webui")
set(BG_WEBUI_STAMP "${BG_WEBUI_BUILD_DIR}/.webui-staged")
if(EXISTS "${BG_WEBUI_SOURCE_DIR}/index.php")
add_custom_command(
OUTPUT "${BG_WEBUI_STAMP}"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${BG_WEBUI_SOURCE_DIR}"
"${BG_WEBUI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E touch "${BG_WEBUI_STAMP}"
DEPENDS "${BG_WEBUI_SOURCE_DIR}/index.php"
COMMENT "Staging BastionGuard WebUI into the build directory"
VERBATIM
)
add_custom_target(BastionGuard-webui ALL
DEPENDS "${BG_WEBUI_STAMP}"
)
install(DIRECTORY "${BG_WEBUI_BUILD_DIR}/"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/webui"
USE_SOURCE_PERMISSIONS
COMPONENT webui
PATTERN ".git" EXCLUDE
PATTERN "*.bak" EXCLUDE
PATTERN "*.tmp" EXCLUDE
PATTERN ".webui-staged" EXCLUDE
)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/data/vhosts/webui/"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data/vhosts/webui"
USE_SOURCE_PERMISSIONS
COMPONENT webui
OPTIONAL
)
install(CODE "
message(STATUS \"[WebUI] Installed in: ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/webui\")
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/cache)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/quarantine)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/sessions)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/lib/bastionguard-webui/tmp)
file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/log/bastionguard-webui)
")
else()
message(WARNING "BastionGuard WebUI source not found at ${BG_WEBUI_SOURCE_DIR}; WebUI will not be installed.")
endif()
# ======================
# BastionGuard Backup (fork di Timeshift, build via Meson)
# ======================
option(ENABLE_BASTIONGUARD_BACKUP "Build bastionguard-backup (Timeshift fork)" ON)
if(ENABLE_BASTIONGUARD_BACKUP)
include(ExternalProject)
find_program(MESON_EXECUTABLE meson REQUIRED)
find_program(NINJA_EXECUTABLE ninja REQUIRED)
find_program(VALAC_EXECUTABLE valac REQUIRED)
find_program(PKG_CONFIG_EXECUTABLE pkg-config REQUIRED)
# Dipendenze runtime/build del fork
pkg_check_modules(BG_BACKUP_GTK3 REQUIRED gtk+-3.0)
pkg_check_modules(BG_BACKUP_GIO REQUIRED gio-2.0 gio-unix-2.0)
pkg_check_modules(BG_BACKUP_JSON REQUIRED json-glib-1.0)
pkg_check_modules(BG_BACKUP_VTE REQUIRED vte-2.91)
pkg_check_modules(BG_BACKUP_GEE REQUIRED gee-0.8)
set(BG_BACKUP_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-backup")
set(BG_BACKUP_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-backup-build")
set(BG_BACKUP_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-backup-install")
message(STATUS "[BG-Backup] Source dir : ${BG_BACKUP_SOURCE_DIR}")
message(STATUS "[BG-Backup] Build dir : ${BG_BACKUP_BINARY_DIR}")
message(STATUS "[BG-Backup] Stage dir : ${BG_BACKUP_INSTALL_DIR}")
message(STATUS "[BG-Backup] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_backup_ext
SOURCE_DIR "${BG_BACKUP_SOURCE_DIR}"
BINARY_DIR "${BG_BACKUP_BINARY_DIR}"
CONFIGURE_COMMAND
${MESON_EXECUTABLE} setup "${BG_BACKUP_BINARY_DIR}" "${BG_BACKUP_SOURCE_DIR}"
--prefix=/usr
--buildtype=release
--reconfigure
BUILD_COMMAND
${MESON_EXECUTABLE} compile -C "${BG_BACKUP_BINARY_DIR}"
INSTALL_COMMAND
${MESON_EXECUTABLE} install -C "${BG_BACKUP_BINARY_DIR}" --destdir "${BG_BACKUP_INSTALL_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-backup ALL
DEPENDS bastionguard_backup_ext
)
install(CODE "
set(BG_BACKUP_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-Backup] =====================================\")
message(STATUS \"[BG-Backup] Installazione bastionguard-backup\")
message(STATUS \"[BG-Backup] Stage dir Meson : ${BG_BACKUP_INSTALL_DIR}\")
message(STATUS \"[BG-Backup] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-Backup] DESTDIR : \${BG_BACKUP_DESTDIR}\")
message(STATUS \"[BG-Backup]\")
set(BG_BACKUP_STAGE_BIN \"${BG_BACKUP_INSTALL_DIR}/usr/bin\")
set(BG_BACKUP_STAGE_SHARE \"${BG_BACKUP_INSTALL_DIR}/usr/share\")
set(BG_BACKUP_STAGE_ETC \"${BG_BACKUP_INSTALL_DIR}/etc\")
set(BG_BACKUP_DEST_BIN \"\${BG_BACKUP_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_BACKUP_DEST_SHARE \"\${BG_BACKUP_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_BACKUP_DEST_ETC \"\${BG_BACKUP_DESTDIR}/etc\")
message(STATUS \"[BG-Backup] Copia binari : \${BG_BACKUP_STAGE_BIN} -> \${BG_BACKUP_DEST_BIN}\")
if(EXISTS \"\${BG_BACKUP_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_BIN}\"
\"\${BG_BACKUP_DEST_BIN}\"
RESULT_VARIABLE BG_BACKUP_BIN_RES
)
if(NOT BG_BACKUP_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando i binari in \${BG_BACKUP_DEST_BIN}\")
endif()
else()
message(WARNING \"[BG-Backup] Directory bin non trovata: \${BG_BACKUP_STAGE_BIN}\")
endif()
message(STATUS \"[BG-Backup] Copia share : \${BG_BACKUP_STAGE_SHARE} -> \${BG_BACKUP_DEST_SHARE}\")
if(EXISTS \"\${BG_BACKUP_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_SHARE}\"
\"\${BG_BACKUP_DEST_SHARE}\"
RESULT_VARIABLE BG_BACKUP_SHARE_RES
)
if(NOT BG_BACKUP_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando share in \${BG_BACKUP_DEST_SHARE}\")
endif()
else()
message(WARNING \"[BG-Backup] Directory share non trovata: \${BG_BACKUP_STAGE_SHARE}\")
endif()
message(STATUS \"[BG-Backup] Copia etc : \${BG_BACKUP_STAGE_ETC} -> \${BG_BACKUP_DEST_ETC}\")
if(EXISTS \"\${BG_BACKUP_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_BACKUP_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_BACKUP_STAGE_ETC}\"
\"\${BG_BACKUP_DEST_ETC}\"
RESULT_VARIABLE BG_BACKUP_ETC_RES
)
if(NOT BG_BACKUP_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-Backup] Errore copiando etc in \${BG_BACKUP_DEST_ETC}\")
endif()
else()
message(STATUS \"[BG-Backup] Nessuna directory etc da installare\")
endif()
message(STATUS \"[BG-Backup] ✔ installazione completata\")
message(STATUS \"[BG-Backup] =====================================\")
")
endif()
# ======================
# BastionGuard Secure Connection (Meson + Go)
# ======================
option(ENABLE_BASTIONGUARD_SECURE_CONNECTION "Build bastionguard-secure-connection" ON)
if(ENABLE_BASTIONGUARD_SECURE_CONNECTION)
include(ExternalProject)
find_program(MESON_EXECUTABLE meson REQUIRED)
find_program(NINJA_EXECUTABLE ninja REQUIRED)
find_program(GO_EXECUTABLE go REQUIRED)
find_program(PROTOC_EXECUTABLE protoc REQUIRED)
find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin REQUIRED)
find_program(PKG_CONFIG_EXECUTABLE pkg-config REQUIRED)
set(BG_SC_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-secure-connection")
set(BG_SC_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-secure-connection-build")
set(BG_SC_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-secure-connection-install")
message(STATUS "[BG-SC] Source dir : ${BG_SC_SOURCE_DIR}")
message(STATUS "[BG-SC] Build dir : ${BG_SC_BINARY_DIR}")
message(STATUS "[BG-SC] Stage dir : ${BG_SC_INSTALL_DIR}")
message(STATUS "[BG-SC] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_secure_connection_ext
SOURCE_DIR "${BG_SC_SOURCE_DIR}"
BINARY_DIR "${BG_SC_BINARY_DIR}"
CONFIGURE_COMMAND
${MESON_EXECUTABLE} setup "${BG_SC_BINARY_DIR}" "${BG_SC_SOURCE_DIR}"
--prefix=/usr
--sysconfdir=/etc
--localedir=share/locale
--buildtype=release
--reconfigure
BUILD_COMMAND
${MESON_EXECUTABLE} compile -C "${BG_SC_BINARY_DIR}"
INSTALL_COMMAND
${MESON_EXECUTABLE} install -C "${BG_SC_BINARY_DIR}" --destdir "${BG_SC_INSTALL_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-secure-connection ALL
DEPENDS bastionguard_secure_connection_ext
)
install(CODE "
set(BG_SC_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-SC] =====================================\")
message(STATUS \"[BG-SC] Installazione bastionguard-secure-connection\")
message(STATUS \"[BG-SC] Stage dir Meson : ${BG_SC_INSTALL_DIR}\")
message(STATUS \"[BG-SC] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-SC] DESTDIR : \${BG_SC_DESTDIR}\")
set(BG_SC_STAGE_BIN \"${BG_SC_INSTALL_DIR}/usr/bin\")
set(BG_SC_STAGE_SHARE \"${BG_SC_INSTALL_DIR}/usr/share\")
set(BG_SC_STAGE_ETC \"${BG_SC_INSTALL_DIR}/etc\")
set(BG_SC_STAGE_LIB \"${BG_SC_INSTALL_DIR}/usr/lib\")
set(BG_SC_DEST_BIN \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_SC_DEST_SHARE \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_SC_DEST_ETC \"\${BG_SC_DESTDIR}/etc\")
set(BG_SC_DEST_LIB \"\${BG_SC_DESTDIR}${CMAKE_INSTALL_PREFIX}/lib\")
if(EXISTS \"\${BG_SC_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_BIN}\"
\"\${BG_SC_DEST_BIN}\"
RESULT_VARIABLE BG_SC_BIN_RES
)
if(NOT BG_SC_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando i binari\")
endif()
endif()
if(EXISTS \"\${BG_SC_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_SHARE}\"
\"\${BG_SC_DEST_SHARE}\"
RESULT_VARIABLE BG_SC_SHARE_RES
)
if(NOT BG_SC_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando share\")
endif()
endif()
if(EXISTS \"\${BG_SC_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_ETC}\"
\"\${BG_SC_DEST_ETC}\"
RESULT_VARIABLE BG_SC_ETC_RES
)
if(NOT BG_SC_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando etc\")
endif()
endif()
# ── Copia esplicita config daemon in /etc/bastionguard-secure-connectiond ──
# Meson installa i JSON con sysconfdir=/etc (assoluto), quindi nella stage
# finiscono sempre in <INSTALL_DIR>/etc/bastionguard-secure-connectiond/.
# Con DESTDIR finiscono dentro il pkgdir, senza DESTDIR in /etc di sistema.
set(BG_SC_CONF_SRC \"${BG_SC_INSTALL_DIR}/etc/bastionguard-secure-connectiond\")
set(BG_SC_CONF_DST \"\${BG_SC_DESTDIR}/etc/bastionguard-secure-connectiond\")
if(EXISTS \"\${BG_SC_CONF_SRC}\")
file(MAKE_DIRECTORY \"\${BG_SC_CONF_DST}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_CONF_SRC}\"
\"\${BG_SC_CONF_DST}\"
RESULT_VARIABLE BG_SC_CONF_RES
)
if(NOT BG_SC_CONF_RES EQUAL 0)
message(WARNING \"[BG-SC] Impossibile copiare la config (permessi?): \${BG_SC_CONF_DST}\")
else()
message(STATUS \"[BG-SC] ✔ Config daemon installata: \${BG_SC_CONF_DST}\")
endif()
else()
message(WARNING \"[BG-SC] Directory config non trovata nella stage: \${BG_SC_CONF_SRC}\")
endif()
# ── Copia esplicita autostart in /etc/xdg/autostart ──────────────────
set(BG_SC_AUTOSTART_SRC
\"${BG_SC_INSTALL_DIR}/etc/xdg/autostart/bastionguard-sc-autostart.desktop\")
set(BG_SC_AUTOSTART_DST \"\${BG_SC_DESTDIR}/etc/xdg/autostart/bastionguard-sc-autostart.desktop\")
if(EXISTS \"\${BG_SC_AUTOSTART_SRC}\")
file(MAKE_DIRECTORY \"\${BG_SC_DESTDIR}/etc/xdg/autostart\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy
\"\${BG_SC_AUTOSTART_SRC}\"
\"\${BG_SC_AUTOSTART_DST}\"
RESULT_VARIABLE BG_SC_AUTOSTART_RES
)
if(NOT BG_SC_AUTOSTART_RES EQUAL 0)
message(WARNING \"[BG-SC] Impossibile copiare l'autostart (permessi?): \${BG_SC_AUTOSTART_DST}\")
else()
message(STATUS \"[BG-SC] ✔ Autostart installato: \${BG_SC_AUTOSTART_DST}\")
endif()
else()
message(WARNING \"[BG-SC] File autostart non trovato nella stage: \${BG_SC_AUTOSTART_SRC}\")
endif()
if(EXISTS \"\${BG_SC_STAGE_LIB}\")
file(MAKE_DIRECTORY \"\${BG_SC_DEST_LIB}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_SC_STAGE_LIB}\"
\"\${BG_SC_DEST_LIB}\"
RESULT_VARIABLE BG_SC_LIB_RES
)
if(NOT BG_SC_LIB_RES EQUAL 0)
message(FATAL_ERROR \"[BG-SC] Errore copiando lib\")
endif()
endif()
message(STATUS \"[BG-SC] ✔ installazione completata\")
message(STATUS \"[BG-SC] =====================================\")
")
endif()
# ======================
# BastionGuard Recovery Data (CMake)
# ======================
option(ENABLE_BASTIONGUARD_RECOVERY_DATA "Build bastionguard-recovery-data" ON)
if(ENABLE_BASTIONGUARD_RECOVERY_DATA)
include(ExternalProject)
set(BG_RD_SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/bastionguard-recovery-data")
set(BG_RD_BINARY_DIR "${CMAKE_BINARY_DIR}/bastionguard-recovery-data-build")
set(BG_RD_INSTALL_DIR "${CMAKE_BINARY_DIR}/bastionguard-recovery-data-install")
message(STATUS "[BG-RD] Source dir : ${BG_RD_SOURCE_DIR}")
message(STATUS "[BG-RD] Build dir : ${BG_RD_BINARY_DIR}")
message(STATUS "[BG-RD] Stage dir : ${BG_RD_INSTALL_DIR}")
message(STATUS "[BG-RD] Final prefix: ${CMAKE_INSTALL_PREFIX}")
ExternalProject_Add(bastionguard_recovery_data_ext
SOURCE_DIR "${BG_RD_SOURCE_DIR}"
BINARY_DIR "${BG_RD_BINARY_DIR}"
CONFIGURE_COMMAND
"${CMAKE_COMMAND}" -S "${BG_RD_SOURCE_DIR}" -B "${BG_RD_BINARY_DIR}"
-DCMAKE_INSTALL_PREFIX=/usr
-DCMAKE_BUILD_TYPE=Release
BUILD_COMMAND
"${CMAKE_COMMAND}" --build "${BG_RD_BINARY_DIR}" --parallel
INSTALL_COMMAND
"${CMAKE_COMMAND}" -E env DESTDIR=${BG_RD_INSTALL_DIR}
"${CMAKE_COMMAND}" --install "${BG_RD_BINARY_DIR}"
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LOG_CONFIGURE OFF
LOG_BUILD OFF
LOG_INSTALL OFF
)
add_custom_target(BastionGuard-recovery-data ALL
DEPENDS bastionguard_recovery_data_ext
)
install(CODE "
set(BG_RD_DESTDIR \"\$ENV{DESTDIR}\")
message(STATUS \"[BG-RD] =====================================\")
message(STATUS \"[BG-RD] Installazione bastionguard-recovery-data\")
message(STATUS \"[BG-RD] Stage dir CMake : ${BG_RD_INSTALL_DIR}\")
message(STATUS \"[BG-RD] Prefix finale : ${CMAKE_INSTALL_PREFIX}\")
message(STATUS \"[BG-RD] DESTDIR : \${BG_RD_DESTDIR}\")
set(BG_RD_STAGE_BIN \"${BG_RD_INSTALL_DIR}/usr/bin\")
set(BG_RD_STAGE_SHARE \"${BG_RD_INSTALL_DIR}/usr/share\")
set(BG_RD_STAGE_ETC \"${BG_RD_INSTALL_DIR}/etc\")
set(BG_RD_STAGE_LIB \"${BG_RD_INSTALL_DIR}/usr/lib\")
set(BG_RD_DEST_BIN \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")
set(BG_RD_DEST_SHARE \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/share\")
set(BG_RD_DEST_ETC \"\${BG_RD_DESTDIR}/etc\")
set(BG_RD_DEST_LIB \"\${BG_RD_DESTDIR}${CMAKE_INSTALL_PREFIX}/lib\")
if(EXISTS \"\${BG_RD_STAGE_BIN}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_BIN}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_BIN}\"
\"\${BG_RD_DEST_BIN}\"
RESULT_VARIABLE BG_RD_BIN_RES
)
if(NOT BG_RD_BIN_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando i binari\")
endif()
else()
message(WARNING \"[BG-RD] Directory bin non trovata: \${BG_RD_STAGE_BIN}\")
endif()
if(EXISTS \"\${BG_RD_STAGE_SHARE}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_SHARE}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_SHARE}\"
\"\${BG_RD_DEST_SHARE}\"
RESULT_VARIABLE BG_RD_SHARE_RES
)
if(NOT BG_RD_SHARE_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando share\")
endif()
else()
message(WARNING \"[BG-RD] Directory share non trovata: \${BG_RD_STAGE_SHARE}\")
endif()
if(EXISTS \"\${BG_RD_STAGE_ETC}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_ETC}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_ETC}\"
\"\${BG_RD_DEST_ETC}\"
RESULT_VARIABLE BG_RD_ETC_RES
)
if(NOT BG_RD_ETC_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando etc\")
endif()
else()
message(STATUS \"[BG-RD] Nessuna directory etc da installare\")
endif()
if(EXISTS \"\${BG_RD_STAGE_LIB}\")
file(MAKE_DIRECTORY \"\${BG_RD_DEST_LIB}\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
\"\${BG_RD_STAGE_LIB}\"
\"\${BG_RD_DEST_LIB}\"
RESULT_VARIABLE BG_RD_LIB_RES
)
if(NOT BG_RD_LIB_RES EQUAL 0)
message(FATAL_ERROR \"[BG-RD] Errore copiando lib\")
endif()
endif()
message(STATUS \"[BG-RD] ✔ installazione completata\")
message(STATUS \"[BG-RD] =====================================\")
")
endif()
# ======================
# Traduzioni con gettext
# ======================
@ -1741,6 +2285,7 @@ install(FILES data/service/org.BastionGuard.RansomwareAlert.service
install(FILES actions/policy/org.BastionGuard.policy
FILES actions/policy/org.BastionGuard.ransomware.policy
FILES actions/policy/org.BastionGuard.USBD.policy
FILES actions/policy/eu.bastionguard.install-ca.policy
DESTINATION /usr/share/polkit-1/actions
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
@ -1748,7 +2293,7 @@ install(FILES actions/dbus/org.BastionGuard.USBD.conf
DESTINATION /usr/share/dbus-1/system.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# Install DBus activation service (system bus)
# Install DBus system service
install(
FILES actions/dbus/org.BastionGuard.USBD.service
DESTINATION /usr/share/dbus-1/system-services
@ -1762,11 +2307,37 @@ install(FILES actions/policy/it.BastionGuard.camera.policy
DESTINATION /usr/share/polkit-1/actions
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# ======================
# Permission Policy – Privacy Webcam
# ======================
install(FILES data/sudoers/bastionguard-helper
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# ======================
# Permission Policy – Bank helper
# ======================
install(FILES data/sudoers/bastionguard-bank
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# ======================
# Permission Policy – Helper anti-phishing-update
# ======================
install(FILES data/sudoers/bastionguard-phishing
DESTINATION /etc/sudoers.d
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
install(PROGRAMS
data/scripts/bank-helper
DESTINATION /usr/bin/
)
# ======================
# Services
# ======================
# opzione per abilitare auto attivazione user units durante 'cmake --install' (default OFF)
# opzione per abilitare automaticamente le user units durante 'cmake --install' (default OFF)
option(ENABLE_USER_AGENT_AUTO "Attempt to enable systemd --user unit for logged-in users at install time" OFF)
# install system units (system-wide)
@ -1791,6 +2362,7 @@ install(FILES
data/service/BastionGuard-pacd.service
data/service/BastionGuard-cef.service
data/service/BastionGuard-mailproxy.service
data/service/BastionGuard-user-session-watch.service
DESTINATION /usr/lib/systemd/user
)
@ -1804,6 +2376,7 @@ install(PROGRAMS
data/scripts/BastionGuard-export-env.sh
data/scripts/BastionGuard-locale.sh
data/scripts/BastionGuard-setup-clamav-daemon.sh
data/scripts/BastionGuard-user-session-watch.sh
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/BastionGuard/data/scripts
)

222
sanitize_po_keep_last.py Executable file
View file

@ -0,0 +1,222 @@
#!/usr/bin/env python3
import sys
import re
import ast
if len(sys.argv) != 3:
print("Usage: sanitize_po_keep_last.py input.po output.po", file=sys.stderr)
sys.exit(1)
input_file = sys.argv[1]
output_file = sys.argv[2]
with open(input_file, "r", encoding="utf-8") as f:
content = f.read()
def split_entries(text):
entries = []
current = []
for line in text.splitlines(keepends=True):
if line.strip() == "":
if current:
entries.append("".join(current))
current = []
else:
current.append(line)
if current:
entries.append("".join(current))
return entries
def read_po_string(lines, start_index):
value = ""
i = start_index
first = lines[i].strip()
m = re.match(
r'^(msgctxt|msgid|msgid_plural|msgstr(?:\[[0-9]+\])?)\s+(.*)$',
first
)
if not m:
return "", i
raw = m.group(2).strip()
try:
value += ast.literal_eval(raw)
except Exception:
pass
i += 1
while i < len(lines):
s = lines[i].strip()
if not s.startswith('"'):
break
try:
value += ast.literal_eval(s)
except Exception:
pass
i += 1
return value, i - 1
def entry_key(entry):
lines = entry.splitlines()
msgctxt = None
msgid = None
i = 0
while i < len(lines):
stripped = lines[i].strip()
if stripped.startswith("msgctxt "):
msgctxt, i = read_po_string(lines, i)
elif stripped.startswith("msgid "):
msgid, i = read_po_string(lines, i)
break
i += 1
if msgid is None:
return None
return (msgctxt, msgid)
def po_quote(s):
return '"' + s.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n") + '"'
def clean_conflict_msgstr(entry):
"""
Ripulisce i msgstr sporchi generati da merge gettext tipo:
#-#-#-#-# file1.po #-#-#-#-#
Traduzione vecchia
#-#-#-#-# file2.po #-#-#-#-#
Traduzione nuova
Tiene solo l'ultima traduzione utile.
"""
if "#-#-#-#-#" not in entry:
return entry
lines = entry.splitlines()
new_lines = []
i = 0
while i < len(lines):
stripped = lines[i].strip()
if stripped.startswith("msgstr "):
msgstr_value, end_i = read_po_string(lines, i)
if "#-#-#-#-#" in msgstr_value:
parts = re.split(
r'#-#-#-#-#.*?#-#-#-#-#\n?',
msgstr_value,
flags=re.DOTALL
)
parts = [p.strip() for p in parts if p.strip()]
chosen = parts[-1] if parts else ""
new_lines.append('msgstr ""')
if chosen:
new_lines.append(po_quote(chosen))
else:
new_lines.extend(lines[i:end_i + 1])
i = end_i + 1
continue
if re.match(r"msgstr\[[0-9]+\]\s+", stripped):
msgstr_value, end_i = read_po_string(lines, i)
if "#-#-#-#-#" in msgstr_value:
parts = re.split(
r'#-#-#-#-#.*?#-#-#-#-#\n?',
msgstr_value,
flags=re.DOTALL
)
parts = [p.strip() for p in parts if p.strip()]
chosen = parts[-1] if parts else ""
prefix = stripped.split(None, 1)[0]
new_lines.append(f'{prefix} ""')
if chosen:
new_lines.append(po_quote(chosen))
else:
new_lines.extend(lines[i:end_i + 1])
i = end_i + 1
continue
new_lines.append(lines[i])
i += 1
return "\n".join(new_lines) + "\n"
entries = split_entries(content)
header_entries = []
normal_entries = []
for entry in entries:
if not entry.strip():
continue
key = entry_key(entry)
# Header gettext: msgid ""
if key == (None, ""):
header_entries.append(clean_conflict_msgstr(entry))
continue
if key is None:
header_entries.append(entry)
continue
normal_entries.append((key, clean_conflict_msgstr(entry)))
# Tiene SOLO l'ultima occorrenza per ogni coppia msgctxt/msgid.
last_by_key = {}
order = []
for key, entry in normal_entries:
if key not in last_by_key:
order.append(key)
last_by_key[key] = entry
with open(output_file, "w", encoding="utf-8") as f:
for entry in header_entries:
f.write(entry.rstrip())
f.write("\n\n")
for key in order:
f.write(last_by_key[key].rstrip())
f.write("\n\n")

View file

@ -20,12 +20,21 @@
#include "Resource.hpp"
#include "AboutPage.hpp"
#include "DistroUtils.hpp"
#include <giomm/file.h>
#include <fstream>
#include <sstream>
#include <ctime>
#include <iostream>
#include <filesystem>
#include <glib/gi18n.h>
#include <glibmm/spawn.h>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <glibmm/spawn.h>
#include <glibmm/error.h>
#include <exception>
std::pair<std::string, std::string> AboutPage::load_version_build() {
namespace fs = std::filesystem;
@ -134,16 +143,16 @@ AboutPage::AboutPage() : Gtk::Box(Gtk::Orientation::VERTICAL) {
// ===== Tab Terze Parti =====
auto box_thirdparty = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 8);
auto label_thirdparty = Gtk::make_managed<Gtk::Label>(
Glib::ustring thirdparty_text =
_("Questa applicazione utilizza:\n"
"- ClamAV Antivirus Engine\n"
"- GTK4 / gtkmm-4\n"
"- SysTray / QT6\n"
"- Image / libpng\n"
"- Rules / yara\n"
"- Udev\n"
"- Libudev\n"
"- Nginx\n"
"- php\n"
"- Sigc++\n"
"- Libsecret\n"
"- IDN2\n"
@ -153,10 +162,13 @@ AboutPage::AboutPage() : Gtk::Box(Gtk::Orientation::VERTICAL) {
"- Polkit\n"
"- Nlohmann_json\n"
"- DNSmasq /blocco pagine\n"
"- Antiphishing server/ libsoup\n"
"- Sandbox bancario/ chromium sandbox (CEF)\n"
"- MISP lista per le banche\n")
);
"- Antiphishing server/ libsoup\n");
if (BastionGuard::Platform::cef_available()) {
thirdparty_text += _("- Sandbox bancario/ chromium sandbox (CEF)\n");
}
thirdparty_text += _("- MISP lista per le banche\n");
auto label_thirdparty = Gtk::make_managed<Gtk::Label>(thirdparty_text);
label_thirdparty->set_wrap(true);
box_thirdparty->append(*label_thirdparty);
notebook_.append_page(*box_thirdparty, _("Terze Parti"));

View file

@ -21,6 +21,7 @@
#pragma once
#include <gtkmm.h>
#include <string>
#include <utility>
class AboutPage : public Gtk::Box {
public:

View file

@ -20,6 +20,7 @@
#include "Resource.hpp"
#include "AntiRansomwarePage.hpp"
#include "Utils.hpp"
#include <giomm/dbusproxy.h>
#include <glibmm/i18n.h>
#include <iostream>
@ -129,6 +130,10 @@ AntiRansomwarePage::AntiRansomwarePage(Gtk::Window& parent)
AntiRansomwarePage::~AntiRansomwarePage() {
// Invalidare subito l'alive flag: eventuali signal_idle.connect_once
// in coda al main loop faranno early-return invece di toccare `this`.
if (alive_) alive_->store(false, std::memory_order_release);
logThreadRunning = false;
if (logThread.joinable())
logThread.join();
@ -203,9 +208,25 @@ void AntiRansomwarePage::onManualScan() {
}
void AntiRansomwarePage::scanDirectoryRecursively(const std::string& root) {
for (auto& e : fs::recursive_directory_iterator(root)) {
if (e.is_regular_file())
runYaraOnPath(e.path().string());
std::error_code ec;
// skip_permission_denied + overload con error_code: non lanciamo eccezioni
// se una subdirectory è inaccessibile o scompare durante la scansione.
auto it = fs::recursive_directory_iterator(
root, fs::directory_options::skip_permission_denied, ec);
if (ec) {
appendLog(_("❌ Impossibile aprire la directory: ") + root);
return;
}
for (; it != fs::recursive_directory_iterator(); it.increment(ec)) {
if (ec) {
ec.clear();
continue;
}
std::error_code ec_rf;
if (it->is_regular_file(ec_rf) && !ec_rf) {
runYaraOnPath(it->path().string());
}
}
}
@ -223,11 +244,18 @@ void AntiRansomwarePage::loadYaraRules() {
return;
}
for (auto& file : fs::directory_iterator(rulesDir)) {
std::error_code ec;
for (auto& file : fs::directory_iterator(rulesDir, ec)) {
if (ec) break;
if (file.path().extension() == ".yar" || file.path().extension() == ".yara") {
FILE* f = fopen(file.path().c_str(), "r");
FILE* f = std::fopen(file.path().c_str(), "r");
if (!f) {
// Regola non leggibile (permessi, file sparito): logga e continua.
appendLog(_("⚠ Impossibile aprire regola YARA: ") + file.path().string());
continue;
}
yr_compiler_add_file(yaraCompiler, f, nullptr, file.path().c_str());
fclose(f);
std::fclose(f);
}
}
@ -275,13 +303,11 @@ void AntiRansomwarePage::sendAlert(const std::string& file, const std::string& r
proxy->call_sync("ShowAlert", params);
}
catch (...) {
Gtk::MessageDialog dlg(
parentWindow,
Utils::show_message(
&parentWindow,
_("Rilevato ransomware:\n") + file + _("\nRegola: ") + ruleName,
false,
Gtk::MessageType::WARNING, Gtk::ButtonsType::OK, true
Gtk::MessageType::WARNING
);
dlg.present();
}
}
@ -323,8 +349,11 @@ void AntiRansomwarePage::startRealtimeLogReader() {
}
// Inoltra al parser centralizzato
Glib::signal_idle().connect_once([this, line]() {
processLogLine(line);
auto alive = alive_;
Glib::signal_idle().connect_once([this, alive, line]() {
BastionGuard::if_alive(alive, [this, &line]() {
processLogLine(line);
});
});
}
});

View file

@ -28,6 +28,8 @@
#include <thread>
#include <atomic>
#include "LifetimeGuard.hpp"
class AntiRansomwarePage : public Gtk::Box {
public:
AntiRansomwarePage(Gtk::Window& parent);
@ -75,6 +77,10 @@ private:
std::thread logThread;
std::atomic<bool> logThreadRunning{false};
// Alive flag: proteggere signal_idle.connect_once che possono
// eseguirsi dopo la distruzione della pagina.
BastionGuard::AliveFlag alive_ = BastionGuard::make_alive_flag();
void startRealtimeLogReader();
void processLogLine(const std::string& line);
};

BIN
src/Archivio.zip Normal file

Binary file not shown.

View file

@ -20,6 +20,7 @@
#include "Resource.hpp"
#include "Backend.hpp"
#include "Utils.hpp"
#include "Quarantine.hpp"
#include "firewall/FirewallRuleManager.hpp"
#include "firewall/BlacklistIpExtractor.hpp"
@ -280,12 +281,22 @@ void Backend::setSambaEnabled(bool enabled) {
std::pair<int,int> read_ports_from_conf()
{
constexpr int default_http_port = 81;
constexpr int default_https_port = 444;
std::ifstream f("/etc/BastionGuard/webports.conf");
int http_port = 80, https_port = 443;
if (f.is_open()) {
f >> http_port >> https_port;
if (!f.is_open())
return {default_http_port, default_https_port};
int http_port = default_http_port;
int https_port = default_https_port;
if ((f >> http_port >> https_port) &&
http_port > 0 && http_port < 65536 &&
https_port > 0 && https_port < 65536) {
return {http_port, https_port};
}
return {http_port, https_port};
return {default_http_port, default_https_port};
}
static void restart_clamd() {
@ -538,7 +549,9 @@ std::string Backend::getLastUpdateDate() {
return _("sconosciuta");
char buf[64];
std::strftime(buf, sizeof(buf), "%d %B %Y %H:%M", std::localtime(&newest));
std::tm tmbuf{};
localtime_r(&newest, &tmbuf); // thread-safe
std::strftime(buf, sizeof(buf), "%d %B %Y %H:%M", &tmbuf);
return buf;
}
@ -795,12 +808,13 @@ Backend::Backend()
}
}
const int default_warning_port = 8080;
const auto [warning_port, warning_https_port] = read_ports_from_conf();
(void)warning_https_port;
if (!blacklist.empty() && std::filesystem::exists(blacklist)) {
try {
webprobe_ = std::make_unique<WebProbe>(blacklist, default_warning_port);
std::cout << _("[Backend] WebProbe avviato su porta ") << default_warning_port
webprobe_ = std::make_unique<WebProbe>(blacklist, warning_port);
std::cout << _("[Backend] WebProbe avviato su porta ") << warning_port
<< _(" con blacklist: ") << blacklist << std::endl;
} catch (const std::exception& ex) {
std::cerr << _("[Backend] Errore inizializzazione WebProbe: ") << ex.what() << std::endl;
@ -996,7 +1010,85 @@ bool Backend::updateYaraRules(std::function<void(int, int, const std::string&)>
// ---------------------------------------------------------------------------
// Helper: esegue lo script privilegiato in modalità silenziosa (NOPASSWD)
// Lo script si trova in /usr/share/BastionGuard/data/scripts/
// ---------------------------------------------------------------------------
static bool run_phishing_updater_script() {
const std::string helper =
"/usr/share/BastionGuard/data/scripts/BastionGuard-phishing-updater.sh";
if (!std::filesystem::exists(helper)) {
std::cerr << _("[Phishing] Helper non trovato: ") << helper
<< _(", fallback a pkexec diretto\n");
return false;
}
// sudo -n = non-interactive, richiede NOPASSWD in /etc/sudoers.d/bastionguard-phishing
std::string cmd = "sudo -n " + helper + " 2>/dev/null";
int ret = std::system(cmd.c_str());
if (ret == 0) return true;
std::cerr << _("[Phishing] sudo -n fallito (ret=") << ret
<< _("), provo pkexec...\n");
ret = std::system(("pkexec " + helper).c_str());
return (ret == 0);
}
// ---------------------------------------------------------------------------
// mergeWhitelistSources: unifica whitelist.json e whitelist.txt evitando dup
// ---------------------------------------------------------------------------
void Backend::mergeWhitelistSources() {
// Ricarica whitelist.json in whitelist_
loadWhitelist();
const std::string txtPath =
Glib::get_home_dir() +
"/.local/share/BastionGuard/phishing/whitelist.txt";
if (!std::filesystem::exists(txtPath)) return;
std::ifstream f(txtPath);
if (!f.is_open()) return;
bool changed = false;
std::string line;
while (std::getline(f, line)) {
// trim
const char* ws = " \t\r\n\f\v";
size_t s = line.find_first_not_of(ws);
if (s == std::string::npos) continue;
size_t e = line.find_last_not_of(ws);
line = line.substr(s, e - s + 1);
if (line.empty() || line[0] == '#') continue;
if (std::find(whitelist_.begin(), whitelist_.end(), line)
== whitelist_.end()) {
whitelist_.push_back(line);
changed = true;
}
}
f.close();
if (changed) {
// Risalva JSON unificato
saveWhitelist();
// Riscrive anche il .txt con il contenuto unificato
std::ofstream out(txtPath, std::ios::trunc);
if (out.is_open())
for (const auto& d : whitelist_)
out << d << "\n";
std::cout << _("[Backend] ✅ Whitelist merged: ")
<< whitelist_.size() << " voci totali\n";
}
}
bool Backend::updatePhishLists() {
// Unifica whitelist.json + whitelist.txt prima di procedere
mergeWhitelistSources();
namespace fs = std::filesystem;
std::string userBase = getRuntimeDataDir();
@ -1005,7 +1097,7 @@ bool Backend::updatePhishLists() {
std::string finalReduce = baseDir + "/blacklist-reduce.txt";
std::string tmpPath = "/tmp/blacklist.txt";
std::string tmpReduce = "/tmp/blacklist-reduce.txt";
std::string tmpDnsmasq = "/tmp/BastionGuard-dnsmasq.conf.tmp";
std::string tmpDnsmasq = "/tmp/BastionGuard-dnsmasq-blacklist.conf";
fs::create_directories(baseDir);
@ -1127,8 +1219,17 @@ bool Backend::updatePhishLists() {
std::string systemDestReduce = "/usr/share/BastionGuard/data/phishing/blacklist-reduce.txt";
copy_to_final(tmpPath, finalPath);
copy_to_final(tmpReduce, finalReduce);
install_to_system_data(tmpPath, systemDest);
install_to_system_data(tmpReduce, systemDestReduce);
try {
fs::copy_file(tmpPath,
"/tmp/bastionguard-blacklist.txt",
fs::copy_options::overwrite_existing);
fs::copy_file(tmpReduce,
"/tmp/bastionguard-blacklist-reduce.txt",
fs::copy_options::overwrite_existing);
} catch (const std::exception& ex) {
std::cerr << _("[Phishing] Errore copia tmp: ") << ex.what() << "\n";
}
try {
@ -1136,14 +1237,13 @@ bool Backend::updatePhishLists() {
if (!fin.is_open()) {
std::cerr << _("❌ Impossibile aprire la blacklist per generare dnsmasq.") << std::endl;
} else {
std::ofstream fout("/tmp/BastionGuard-dnsmasq-blacklist.conf", std::ios::trunc);
std::ofstream fout(tmpDnsmasq, std::ios::trunc);
if (!fout.is_open()) {
std::cerr << _("❌ Impossibile creare file temporaneo dnsmasq.") << std::endl;
} else {
static const std::unordered_set<std::string> infra_whitelist = {
// code hosting / repos
"github.com",
"githubusercontent.com",
"gitlab.com",
@ -1182,11 +1282,13 @@ bool Backend::updatePhishLists() {
std::unordered_set<std::string> trusted;
auto load_json_list = [&](const std::string& path) {
if (!fs::exists(path)) return;
try {
std::ifstream f(path);
nlohmann::json j; f >> j;
nlohmann::json j;
f >> j;
auto push_str = [&](const nlohmann::json& arr) {
for (auto& v : arr) {
@ -1204,18 +1306,70 @@ bool Backend::updatePhishLists() {
} catch (...) {}
};
auto load_text_list = [&](const std::string& path) {
if (!fs::exists(path)) return;
try {
std::ifstream f(path);
std::string line;
while (std::getline(f, line)) {
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
line.erase(std::remove(line.begin(), line.end(), '\n'), line.end());
const char* ws = " \t\f\v";
size_t start = line.find_first_not_of(ws);
if (start == std::string::npos) continue;
size_t end = line.find_last_not_of(ws);
line = line.substr(start, end - start + 1);
if (line.empty() || line[0] == '#')
continue;
trusted.insert(line);
}
} catch (...) {}
};
load_json_list("/usr/share/BastionGuard/data/bank/banks.json");
if (const char* home = std::getenv("HOME"))
if (const char* home = std::getenv("HOME")) {
load_json_list(std::string(home) + "/.config/BastionGuard/whitelist.json");
load_text_list(std::string(home) + "/.local/share/BastionGuard/phishing/whitelist.txt");
}
auto clean_domain = [](std::string s) {
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c){ return (char)std::tolower(c); });
if (s.rfind("www.", 0) == 0) s.erase(0, 4);
while (!s.empty() && s.front() == '.') s.erase(0, 1);
while (!s.empty() && s.back() == '.') s.pop_back();
return s;
};
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c){ return (char)std::tolower(c); });
const char* ws = " \t\r\n\f\v";
size_t start = s.find_first_not_of(ws);
if (start == std::string::npos) return std::string{};
size_t end = s.find_last_not_of(ws);
s = s.substr(start, end - start + 1);
if (auto pos = s.find("://"); pos != std::string::npos)
s = s.substr(pos + 3);
for (char c : {'/', ' ', ';', '"', '\'', '%', '&', '(', ')', '=', '?', '*', '#'})
if (auto p = s.find(c); p != std::string::npos)
s = s.substr(0, p);
if (auto at = s.rfind('@'); at != std::string::npos)
s = s.substr(at + 1);
if (auto colon = s.find(':'); colon != std::string::npos)
s = s.substr(0, colon);
if (s.rfind("www.", 0) == 0)
s.erase(0, 4);
while (!s.empty() && s.front() == '.')
s.erase(0, 1);
while (!s.empty() && s.back() == '.')
s.pop_back();
return s;
};
auto is_whitelisted_domain = [&](const std::string& domain,
@ -1304,18 +1458,23 @@ bool Backend::updatePhishLists() {
<< _(" voci. Skipped whitelist: ") << skipped
<< _(" | Skipped IP: ") << skipped_ip << "\n";
install_to_system_data("/tmp/BastionGuard-dnsmasq-blacklist.conf",
"/etc/dnsmasq.d/BastionGuard-blacklist.conf");
system("dnsmasq --test > /tmp/BastionGuard-dnsmasq.log 2>&1");
reload_dnsmasq();
fs::remove("/tmp/BastionGuard-dnsmasq-blacklist.conf");
bool script_ok = run_phishing_updater_script();
if (!script_ok) {
install_to_system_data(tmpPath, systemDest);
install_to_system_data(tmpReduce, systemDestReduce);
install_to_system_data(tmpDnsmasq,
"/etc/dnsmasq.d/BastionGuard-blacklist.conf");
system("dnsmasq --test > /tmp/BastionGuard-dnsmasq.log 2>&1");
reload_dnsmasq();
}
fs::remove(tmpDnsmasq);
}
}
} catch (const std::exception& e) {
std::cerr << _("⚠ Errore generazione dnsmasq blocklist: ") << e.what() << std::endl;
}
return true;
try {
@ -1407,7 +1566,7 @@ bool Backend::updateSanesecurityDB(std::function<void(int, int, const std::strin
for (const auto& db : dbs) {
++current;
if (progressCallback)
progressCallback(current - 1, total, db); // aggiornamento prima del download
progressCallback(current - 1, total, db);
std::string url = "https://sanesecurity.com/clamav/" + db;
std::string dest = tmpDir + "/" + db;
@ -1423,16 +1582,16 @@ bool Backend::updateSanesecurityDB(std::function<void(int, int, const std::strin
std::cerr << _("⚠ Errore download o file vuoto: ") << db << "\n";
if (progressCallback)
progressCallback(current, total, db);
continue; // passa al prossimo file
continue;
}
// Copia locale
if (!copy_to_final(dest, finalPath)) {
std::cerr << _("❌ Errore copia locale ") << finalPath << "\n";
return false;
}
// Copia system-wide (se permessi)
if (install_to_system_data(dest, systemDest)) {
std::cout << _("") << db << _(" installato system-wide in ") << systemDest << "\n";
} else {
@ -1558,7 +1717,6 @@ bool Backend::testGoogleSafeKey() {
curl_easy_cleanup(curl);
// Analisi della risposta
if (response.find("threatType") != std::string::npos) {
std::cout << "[Backend] ✔ " << _("Chiave Google Safe valida e attiva") << "\n";
return true;
@ -2605,15 +2763,10 @@ void Backend::moveToQuarantine(const std::string& path) {
Glib::signal_idle().connect_once([dest]() {
auto dialog = Gtk::make_managed<Gtk::MessageDialog>(
Utils::show_message(
nullptr,
_("File spostato in quarantena con successo:\n") + dest.string(),
false,
Gtk::MessageType::INFO,
Gtk::ButtonsType::OK,
true
);
dialog->set_title(_("Quarantena completata"));
dialog->present();
Gtk::MessageType::INFO);
});
} catch (const std::exception& ex) {
@ -2974,4 +3127,3 @@ void Backend::scheduleFirewallApply() {
Backend::~Backend() = default;

View file

@ -75,6 +75,7 @@ public:
void removeFromWhitelist(const std::string& domain);
void saveWhitelist() const;
void loadWhitelist();
void mergeWhitelistSources();
bool isBankDomain(const std::string& host) const;
std::function<void(const std::string&)> onBankListReload;
bool updateBankListFromURL(const std::string& source_url);
@ -210,7 +211,6 @@ private:
void initSambaClient();
std::string getSambaCredsPath() const;
void loadSMBCredentials();
// Stato scansione
std::string samba_last_temp_dir;
float samba_last_progress = 0.0f;
};

View file

@ -25,14 +25,95 @@
#include <filesystem>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <cctype>
#include <unordered_set>
#include <system_error>
#include <nlohmann/json.hpp>
#include <glibmm/i18n.h>
#include <glibmm/miscutils.h>
#include <glibmm/datetime.h>
#include <cstdlib>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
using json = nlohmann::json;
namespace fs = std::filesystem;
namespace {
static std::string trim_copy(std::string s) {
auto l = s.find_first_not_of(" \t\r\n");
auto r = s.find_last_not_of(" \t\r\n");
if (l == std::string::npos) return {};
return s.substr(l, r - l + 1);
}
static std::string normalize_domain(std::string domain) {
domain = trim_copy(domain);
if (domain.empty()) return {};
auto pos = domain.find("://");
if (pos != std::string::npos)
domain.erase(0, pos + 3);
pos = domain.find('/');
if (pos != std::string::npos)
domain.erase(pos);
pos = domain.find('@');
if (pos != std::string::npos)
domain = domain.substr(pos + 1);
pos = domain.find(':');
if (pos != std::string::npos)
domain.erase(pos);
if (domain.rfind("www.", 0) == 0)
domain.erase(0, 4);
std::transform(domain.begin(), domain.end(), domain.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
if (!domain.empty() && domain.front() == '.')
domain.erase(domain.begin());
while (!domain.empty() && domain.back() == '.')
domain.pop_back();
domain = trim_copy(domain);
if (domain.empty()) return {};
if (domain.find('.') == std::string::npos) return {};
return domain;
}
static std::string iso_today_yyyy_mm_dd() {
auto now = Glib::DateTime::create_now_local();
return now.format("%Y-%m-%d");
}
static void restart_cef_service_user() {
int rc = std::system("systemctl --user restart BastionGuard-cef.service >/dev/null 2>&1");
if (rc == 0)
std::cout << _("[BankPage] ✔ BastionGuard-cef.service riavviato\n");
else
std::cerr << _("[BankPage] ⚠ Impossibile riavviare BastionGuard-cef.service\n");
}
} // namespace
BankPage::~BankPage()
{
if (alive_) alive_->store(false, std::memory_order_release);
if (auto_update_conn_.connected()) auto_update_conn_.disconnect();
}
BankPage::BankPage()
: Gtk::Box(Gtk::Orientation::VERTICAL, 12)
{
@ -60,13 +141,11 @@ BankPage::BankPage()
append(*title_box);
entry_url_.set_placeholder_text(_("URL sorgente (es. MISP bank-website/list.json)"));
entry_url_.set_text("https://raw.githubusercontent.com/MISP/misp-warninglists/main/lists/bank-website/list.json");
entry_url_.set_margin_bottom(6);
append(entry_url_);
btn_refresh_.set_label(_("🔄 Aggiorna lista"));
btn_refresh_.set_margin_bottom(12);
append(btn_refresh_);
@ -79,7 +158,55 @@ BankPage::BankPage()
toggle_box->set_margin_bottom(12);
append(*toggle_box);
auto whitelist_box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
whitelist_entry_.set_placeholder_text(_("Aggiungi dominio alla whitelist..."));
whitelist_entry_.set_hexpand(true);
btn_add_whitelist_.set_label(_("➕ Aggiungi"));
whitelist_box->append(whitelist_entry_);
whitelist_box->append(btn_add_whitelist_);
append(*whitelist_box);
// -------------------------------------------------------------------------
// Apertura banca dentro sandbox sicura (BastionGuard-secure + bubblewrap).
// L'URL viene passato a /usr/bin/BastionGuard-secure-cli, che a sua volta
// si re-exec dentro bwrap (Wayland o X11) prima di aprire CEF.
// -------------------------------------------------------------------------
auto open_bank_box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
open_bank_entry_.set_placeholder_text(_("Apri URL banca (es. https://www.intesasanpaolo.com)..."));
open_bank_entry_.set_hexpand(true);
btn_open_bank_.set_label(_("🔐 Apri in sandbox sicura"));
open_bank_box->append(open_bank_entry_);
open_bank_box->append(btn_open_bank_);
open_bank_box->set_margin_top(4);
open_bank_box->set_margin_bottom(8);
append(*open_bank_box);
scroller_banks_.set_vexpand(true);
scroller_banks_.set_hexpand(true);
txt_banks_.set_editable(false);
txt_banks_.set_wrap_mode(Gtk::WrapMode::WORD_CHAR);
scroller_banks_.set_child(txt_banks_);
append(scroller_banks_);
scroller_white_.set_vexpand(true);
scroller_white_.set_hexpand(true);
txt_whitelist_.set_editable(false);
txt_whitelist_.set_wrap_mode(Gtk::WrapMode::WORD_CHAR);
scroller_white_.set_child(txt_whitelist_);
append(scroller_white_);
lbl_status_.set_margin_top(8);
append(lbl_status_);
load_settings();
load_whitelist();
merge_whitelist_into_banks_json();
populate_bank_list();
btn_refresh_.signal_clicked().connect(sigc::mem_fun(*this, &BankPage::on_refresh_clicked));
btn_add_whitelist_.signal_clicked().connect(sigc::mem_fun(*this, &BankPage::on_add_whitelist_clicked));
btn_open_bank_.signal_clicked().connect(sigc::mem_fun(*this, &BankPage::on_open_bank_clicked));
open_bank_entry_.signal_activate().connect(sigc::mem_fun(*this, &BankPage::on_open_bank_clicked));
auto_update_switch_.property_active().signal_changed().connect([this]() {
auto_update_enabled_ = auto_update_switch_.get_active();
@ -99,114 +226,93 @@ BankPage::BankPage()
start_auto_update_timer();
lbl_status_.set_text(_("🔁 Aggiornamento automatico attivo."));
}
btn_refresh_.signal_clicked().connect(sigc::mem_fun(*this, &BankPage::on_refresh_clicked));
btn_add_whitelist_.signal_clicked().connect(sigc::mem_fun(*this, &BankPage::on_add_whitelist_clicked));
load_whitelist();
populate_bank_list();
Glib::signal_timeout().connect_seconds(
sigc::mem_fun(*this, &BankPage::auto_update_bank_list),
6 * 60 * 60
);
auto whitelist_box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
whitelist_entry_.set_placeholder_text(_("Aggiungi dominio alla whitelist..."));
whitelist_entry_.set_hexpand(true);
btn_add_whitelist_.set_label(_("➕ Aggiungi"));
whitelist_box->append(whitelist_entry_);
whitelist_box->append(btn_add_whitelist_);
append(*whitelist_box);
scroller_banks_.set_vexpand(true);
scroller_banks_.set_hexpand(true);
txt_banks_.set_editable(false);
txt_banks_.set_wrap_mode(Gtk::WrapMode::WORD_CHAR);
scroller_banks_.set_child(txt_banks_);
append(scroller_banks_);
scroller_white_.set_vexpand(true);
scroller_white_.set_hexpand(true);
txt_whitelist_.set_editable(false);
txt_whitelist_.set_wrap_mode(Gtk::WrapMode::WORD_CHAR);
scroller_white_.set_child(txt_whitelist_);
append(scroller_white_);
lbl_status_.set_margin_top(8);
append(lbl_status_);
btn_refresh_.signal_clicked().connect(sigc::mem_fun(*this, &BankPage::on_refresh_clicked));
btn_add_whitelist_.signal_clicked().connect(sigc::mem_fun(*this, &BankPage::on_add_whitelist_clicked));
load_whitelist();
populate_bank_list();
Glib::signal_timeout().connect_seconds(
sigc::mem_fun(*this, &BankPage::auto_update_bank_list),
6 * 60 * 60
);
}
void BankPage::on_refresh_clicked() {
lbl_status_.set_text(_("⬇️ Download in corso..."));
btn_refresh_.set_sensitive(false);
std::string url = entry_url_.get_text();
std::thread([this, url]() {
std::thread([this, alive = alive_, url]() {
bool ok = Backend::instance().updateBankListFromURL(url);
if (!alive->load()) return;
Glib::signal_idle().connect_once([this, ok, url]() {
if (ok) {
lbl_status_.set_text(_("✅ Lista aggiornata da MISP."));
copy_banklist_to_system(url);
populate_bank_list();
} else {
lbl_status_.set_text(_("❌ Errore nel download della lista."));
}
btn_refresh_.set_sensitive(true);
Glib::signal_idle().connect_once([this, alive, ok, url]() {
BastionGuard::if_alive(alive, [this, ok, &url]() {
if (ok) {
load_whitelist();
if (merge_whitelist_into_banks_json()) {
copy_banklist_to_system(url);
populate_bank_list();
lbl_status_.set_text(_("✅ Lista aggiornata da MISP, whitelist integrata e servizio CEF riavviato."));
} else {
lbl_status_.set_text(_("⚠ Lista aggiornata da MISP, ma merge whitelist fallito."));
}
} else {
lbl_status_.set_text(_("❌ Errore nel download della lista."));
}
btn_refresh_.set_sensitive(true);
});
});
}).detach();
}
void BankPage::copy_banklist_to_system(const std::string& source_url) {
std::string userPath = Glib::get_home_dir() + "/.local/share/BastionGuard/banks.json";
std::string systemDir = "/usr/share/BastionGuard/data/bank";
std::string systemPath = systemDir + "/banks.json";
const std::string helper = "/usr/bin/bank-helper";
const std::string userPath = Glib::get_home_dir() + "/.local/share/BastionGuard/banks.json";
try {
// Comando pkexec per copiare con privilegi
std::string cmd = "pkexec cp \"" + userPath + "\" \"" + systemPath + "\"";
int rc = std::system(cmd.c_str());
if (rc != 0) {
throw std::runtime_error(_("pkexec fallito o annullato dall'utente"));
// NON usiamo std::system() con il URL interpolato: sarebbe shell injection
// (caratteri come ; | $() ` newline scappano dal quoting).
// Invochiamo sudo + helper direttamente con execvp: ogni argomento è
// un elemento separato di argv, non c'è shell che lo interpreta.
const pid_t pid = ::fork();
if (pid < 0) {
std::cerr << _("[BankPage] ⚠️ fork fallita per bank-helper") << std::endl;
return;
}
if (pid == 0) {
// child: redirige stdout/stderr su /dev/null (equivalente a >/dev/null 2>&1)
int devnull = ::open("/dev/null", O_WRONLY);
if (devnull >= 0) {
::dup2(devnull, STDOUT_FILENO);
::dup2(devnull, STDERR_FILENO);
::close(devnull);
}
// Scrivi il file di versione (sempre come root)
cmd = "pkexec bash -c 'echo \"URL: " + source_url + _("\\nAggiornato il: ") +
Glib::DateTime::create_now_local().format("%Y-%m-%d %H:%M:%S") +
"\" > \"" + systemDir + "/version.txt\"'";
std::system(cmd.c_str());
// argv: sudo, helper, userPath, source_url
// Nota: source_url viene passato come singolo argomento di argv,
// quindi contenuti come "; rm -rf /" restano una stringa letterale.
const char* argv[] = {
"sudo",
helper.c_str(),
userPath.c_str(),
source_url.c_str(),
nullptr
};
::execvp("sudo", const_cast<char* const*>(argv));
_exit(127); // execvp fallito
}
std::cout << _("[BankPage] ✅ Lista copiata in ") << systemPath << std::endl;
} catch (const std::exception& e) {
std::cerr << _("[BankPage] ⚠️ Copia in /usr/share/BastionGuard/data/bank fallita: ") << e.what() << std::endl;
// parent: aspetta il child
int status = 0;
if (::waitpid(pid, &status, 0) < 0) {
std::cerr << _("[BankPage] ⚠️ waitpid fallita per bank-helper") << std::endl;
return;
}
const int rc = WIFEXITED(status) ? WEXITSTATUS(status)
: (WIFSIGNALED(status) ? 128 + WTERMSIG(status) : -1);
if (rc == 0) {
std::cout << _("[BankPage] ✅ Lista copiata in /usr/share/BastionGuard/data/bank/banks.json\n");
} else {
std::cerr << _("[BankPage] ⚠️ bank-helper fallito (rc=") << rc
<< _("). Verificare /etc/sudoers.d/bastionguard-bank e i permessi di bank-helper.\n");
}
}
void BankPage::populate_bank_list() {
std::string path = Glib::get_home_dir() + "/.local/share/BastionGuard/banks.json";
@ -217,8 +323,9 @@ void BankPage::populate_bank_list() {
std::ifstream f(path);
json j;
try { f >> j; }
catch (...) {
try {
f >> j;
} catch (...) {
txt_banks_.get_buffer()->set_text(_("❌ Errore parsing JSON.\n"));
return;
}
@ -229,18 +336,22 @@ void BankPage::populate_bank_list() {
std::vector<std::string> domains;
if (j.contains("list") && j["list"].is_array()) {
for (auto& item : j["list"]) {
if (item.is_string())
if (item.is_string()) {
domains.push_back(item.get<std::string>());
else if (item.contains("value"))
} else if (item.is_object() && item.contains("value") && item["value"].is_string()) {
domains.push_back(item["value"].get<std::string>());
}
}
}
std::sort(domains.begin(), domains.end());
domains.erase(std::unique(domains.begin(), domains.end()), domains.end());
int count = 0;
for (auto& domain : domains) {
std::string clean = domain;
if (!clean.empty() && clean[0] == '.')
clean.erase(0, 1);
std::string clean = normalize_domain(domain);
if (clean.empty()) continue;
if (std::find(whitelist_.begin(), whitelist_.end(), clean) == whitelist_.end()) {
oss_banks << " - " << clean << "\n";
count++;
@ -250,20 +361,20 @@ void BankPage::populate_bank_list() {
oss_banks << _("\nTotale banche: ") << count << "\n";
txt_banks_.get_buffer()->set_text(oss_banks.str());
// Whitelist
std::ostringstream oss_white;
oss_white << _("🛡️ Whitelist:\n\n");
oss_white << _("🛡️ Nuovi domini bancari:\n\n");
for (auto& w : whitelist_)
oss_white << " + " << w << "\n";
if (whitelist_.empty())
oss_white << _("(Nessun dominio whitelistato)\n");
txt_whitelist_.get_buffer()->set_text(oss_white.str());
}
void BankPage::on_add_whitelist_clicked() {
std::string domain = whitelist_entry_.get_text();
std::string domain = normalize_domain(whitelist_entry_.get_text());
if (domain.empty()) {
lbl_status_.set_text(_("⚠ Inserisci un dominio valido."));
return;
@ -271,8 +382,16 @@ void BankPage::on_add_whitelist_clicked() {
if (std::find(whitelist_.begin(), whitelist_.end(), domain) == whitelist_.end()) {
whitelist_.push_back(domain);
std::sort(whitelist_.begin(), whitelist_.end());
whitelist_.erase(std::unique(whitelist_.begin(), whitelist_.end()), whitelist_.end());
save_whitelist();
lbl_status_.set_text(_("✅ Dominio aggiunto alla whitelist."));
if (merge_whitelist_into_banks_json())
lbl_status_.set_text(_("✅ Dominio aggiunto alla whitelist, integrato in banks.json e servizio CEF riavviato."));
else
lbl_status_.set_text(_("⚠ Dominio salvato in whitelist, ma merge su banks.json fallito."));
populate_bank_list();
} else {
lbl_status_.set_text(_("ℹ️ Dominio già presente nella whitelist."));
@ -281,36 +400,152 @@ void BankPage::on_add_whitelist_clicked() {
whitelist_entry_.set_text("");
}
void BankPage::load_whitelist() {
whitelist_.clear();
std::string path = Glib::get_home_dir() + "/.config/BastionGuard/whitelist.json";
if (!fs::exists(path)) return;
if (!fs::exists(path))
return;
std::ifstream f(path);
if (!f.is_open())
return;
json j;
try { f >> j; } catch (...) { return; }
if (j.is_array()) {
for (auto& w : j)
whitelist_.push_back(w.get<std::string>());
try {
f >> j;
} catch (...) {
return;
}
}
if (j.contains("list") && j["list"].is_array()) {
for (const auto& w : j["list"]) {
if (!w.is_string()) continue;
std::string d = normalize_domain(w.get<std::string>());
if (!d.empty())
whitelist_.push_back(d);
}
}
std::sort(whitelist_.begin(), whitelist_.end());
whitelist_.erase(std::unique(whitelist_.begin(), whitelist_.end()), whitelist_.end());
}
void BankPage::save_whitelist() {
std::string dir = Glib::get_home_dir() + "/.config/BastionGuard";
fs::create_directories(dir);
std::vector<std::string> clean = whitelist_;
for (auto& d : clean)
d = normalize_domain(d);
clean.erase(std::remove_if(clean.begin(), clean.end(),
[](const std::string& s) { return s.empty(); }),
clean.end());
std::sort(clean.begin(), clean.end());
clean.erase(std::unique(clean.begin(), clean.end()), clean.end());
json j;
j["version"] = 1;
j["updated_at"] = iso_today_yyyy_mm_dd();
j["enabled"] = true;
j["list"] = json::array();
for (const auto& d : clean)
j["list"].push_back(d);
std::ofstream f(dir + "/whitelist.json", std::ios::trunc);
json j(whitelist_);
if (!f.is_open())
return;
f << j.dump(2);
}
bool BankPage::merge_whitelist_into_banks_json() {
const std::string path = Glib::get_home_dir() + "/.local/share/BastionGuard/banks.json";
json j;
if (fs::exists(path)) {
try {
std::ifstream in(path);
if (in.is_open())
in >> j;
} catch (...) {
j = json::object();
}
}
if (!j.is_object())
j = json::object();
if (!j.contains("list") || !j["list"].is_array())
j["list"] = json::array();
std::unordered_set<std::string> existing;
bool changed = false;
for (const auto& item : j["list"]) {
if (item.is_string()) {
std::string d = normalize_domain(item.get<std::string>());
if (!d.empty())
existing.insert(d);
} else if (item.is_object() && item.contains("value") && item["value"].is_string()) {
std::string d = normalize_domain(item["value"].get<std::string>());
if (!d.empty())
existing.insert(d);
}
}
for (const auto& w : whitelist_) {
std::string d = normalize_domain(w);
if (d.empty()) continue;
if (!existing.count(d)) {
j["list"].push_back("." + d);
existing.insert(d);
changed = true;
}
}
if (!changed) {
std::cout << _("[BankPage] ℹ Nessun merge necessario in banks.json\n");
return true;
}
const std::string tmp = path + ".tmp";
try {
std::ofstream out(tmp, std::ios::trunc);
if (!out.is_open())
return false;
out << j.dump(2);
out.flush();
out.close();
std::error_code ec;
fs::rename(tmp, path, ec);
if (ec) {
fs::remove(path, ec);
ec.clear();
fs::rename(tmp, path, ec);
if (ec) {
fs::remove(tmp, ec);
return false;
}
}
std::cout << _("[BankPage] ✔ whitelist integrata in banks.json\n");
restart_cef_service_user();
return true;
} catch (...) {
try { fs::remove(tmp); } catch (...) {}
return false;
}
}
void BankPage::start_auto_update_timer() {
if (auto_update_conn_)
@ -327,45 +562,57 @@ void BankPage::start_auto_update_timer() {
void BankPage::stop_auto_update_timer() {
if (auto_update_conn_)
auto_update_conn_.disconnect();
std::cout << _("[BankPage] ⏹️ Auto-update disattivato.") << std::endl;
}
bool BankPage::auto_update_bank_list() {
std::string url = entry_url_.get_text();
std::thread([this, url]() {
std::thread([this, alive = alive_, url]() {
std::cout << _("[BankPage] ⏰ Aggiornamento automatico lista banche...") << std::endl;
bool ok = Backend::instance().updateBankListFromURL(url);
if (!alive->load()) return;
Glib::signal_idle().connect_once([this, ok, url]() {
if (ok) {
lbl_status_.set_text(_("✅ Lista aggiornata automaticamente da MISP."));
copy_banklist_to_system(url);
populate_bank_list();
Glib::signal_idle().connect_once([this, alive, ok, url]() {
BastionGuard::if_alive(alive, [this, ok, &url]() {
if (ok) {
load_whitelist();
auto now = Glib::DateTime::create_now_local();
lbl_status_.set_text(_("✅ Lista aggiornata automaticamente il: ") + now.format("%Y-%m-%d %H:%M:%S"));
} else {
lbl_status_.set_text(_("⚠️ Errore nell'aggiornamento automatico."));
}
if (merge_whitelist_into_banks_json()) {
copy_banklist_to_system(url);
populate_bank_list();
auto now = Glib::DateTime::create_now_local();
lbl_status_.set_text(_("✅ Lista aggiornata automaticamente il: ") + now.format("%Y-%m-%d %H:%M:%S"));
} else {
lbl_status_.set_text(_("⚠️ Lista aggiornata, ma merge whitelist fallito."));
}
} else {
lbl_status_.set_text(_("⚠️ Errore nell'aggiornamento automatico."));
}
});
});
}).detach();
return true;
}
void BankPage::load_settings() {
std::string path = Glib::get_home_dir() + "/.config/BastionGuard/settings.json";
if (!fs::exists(path))
return;
std::ifstream f(path);
if (!f.is_open()) return;
if (!f.is_open())
return;
json j;
try { f >> j; } catch (...) { return; }
try {
f >> j;
} catch (...) {
return;
}
if (j.contains("auto_update"))
auto_update_enabled_ = j["auto_update"].get<bool>();
@ -373,8 +620,6 @@ void BankPage::load_settings() {
auto_update_switch_.set_active(auto_update_enabled_);
}
void BankPage::save_settings() {
std::string dir = Glib::get_home_dir() + "/.config/BastionGuard";
fs::create_directories(dir);
@ -384,3 +629,105 @@ void BankPage::save_settings() {
j["auto_update"] = auto_update_enabled_;
f << j.dump(2);
}
// =============================================================================
// Apertura banca in sandbox sicura.
//
// Il bottone "🔐 Apri in sandbox sicura" passa l'URL al binario
// BastionGuard-secure-cli, che:
// 1) si re-exec dentro bubblewrap (con DNS custom + bind X11/Wayland);
// 2) avvia CEF con OZONE_PLATFORM corretto (Wayland o X11);
// 3) fa il match contro payments.json/banks.json e apre la pagina.
//
// Vantaggio: anche le banche nuove (whitelist utente) vengono aperte in
// un processo isolato dal browser di sistema, senza dover passare dal
// proxy CEF (BastionGuard-cef.service).
// =============================================================================
void BankPage::on_open_bank_clicked() {
std::string raw = trim_copy(open_bank_entry_.get_text());
if (raw.empty()) {
lbl_status_.set_text(_("⚠ Inserisci un URL o un dominio bancario."));
return;
}
// Se l'utente ha messo solo il dominio, completiamo con https://
if (raw.find("://") == std::string::npos)
raw = "https://" + raw;
if (open_bank_in_sandbox(raw)) {
lbl_status_.set_text(_("🔐 Apertura sandbox sicura in corso: ") + raw);
} else {
lbl_status_.set_text(_("❌ Apertura sandbox fallita. Vedi log."));
}
}
bool BankPage::open_bank_in_sandbox(const std::string& url) {
if (url.empty()) return false;
// Validazione minima: blocca caratteri pericolosi anche se passiamo
// l'URL come argv separato (non c'è shell-injection, ma evitiamo
// comunque newline e null bytes che confonderebbero il helper).
for (char c : url) {
if (c == '\n' || c == '\r' || c == '\0') {
std::cerr << _("[BankPage] URL contiene caratteri non validi.") << std::endl;
return false;
}
}
// Cerchiamo il binario in path standard. Lo script di sandbox è
// BastionGuard-secure-cli; se non c'è, ripieghiamo su BastionGuard-secure
// (la versione GUI), che fa anch'essa re-exec dentro bwrap.
static const char* candidates[] = {
"/usr/bin/BastionGuard-secure-cli",
"/usr/local/bin/BastionGuard-secure-cli",
"/usr/bin/BastionGuard-secure",
"/usr/local/bin/BastionGuard-secure",
nullptr
};
const char* bin = nullptr;
for (int i = 0; candidates[i]; ++i) {
if (::access(candidates[i], X_OK) == 0) {
bin = candidates[i];
break;
}
}
if (!bin) {
std::cerr << _("[BankPage] BastionGuard-secure-cli non trovato; "
"installa il pacchetto BastionGuard completo.") << std::endl;
return false;
}
std::cout << _("[BankPage] 🔐 Avvio sandbox sicura via ") << bin
<< _(" per URL: ") << url << std::endl;
const pid_t pid = ::fork();
if (pid < 0) {
std::cerr << _("[BankPage] fork() fallita per BastionGuard-secure-cli")
<< std::endl;
return false;
}
if (pid == 0) {
// Child: detach completo dalla GUI principale.
// setsid() così la chiusura della GUI di BastionGuard non killa la sandbox.
::setsid();
// Redirige stdout/stderr per non sporcare la console di BastionGuard.
// (I log finiscono comunque nei journald del servizio se è registrato.)
int devnull = ::open("/dev/null", O_WRONLY);
if (devnull >= 0) {
::dup2(devnull, STDOUT_FILENO);
::dup2(devnull, STDERR_FILENO);
::close(devnull);
}
const char* argv[] = { bin, url.c_str(), nullptr };
::execvp(bin, const_cast<char* const*>(argv));
_exit(127);
}
// Parent: non aspettiamo (è un processo a vita lunga, il browser).
// setsid + non waitpid = detached: corretto per "spawn and forget".
return true;
}

View file

@ -23,12 +23,15 @@
#include <vector>
#include <string>
#include "LifetimeGuard.hpp"
// forward
class SecureBrowser;
class BankPage : public Gtk::Box {
public:
BankPage();
~BankPage() override;
private:
Gtk::Entry entry_url_;
@ -43,6 +46,10 @@ private:
Gtk::TextView txt_whitelist_;
Gtk::Label lbl_status_;
// === Apertura banca dentro sandbox bubblewrap ===
Gtk::Entry open_bank_entry_;
Gtk::Button btn_open_bank_;
std::vector<std::string> whitelist_;
std::string selected_bank_url_;
@ -54,7 +61,11 @@ private:
void on_add_whitelist_clicked();
void on_open_browser_clicked();
void on_close_browser_clicked();
bool merge_whitelist_into_banks_json();
// Apre l'URL banca dentro BastionGuard-secure (CEF + bwrap, Wayland o X11).
void on_open_bank_clicked();
bool open_bank_in_sandbox(const std::string& url);
void populate_bank_list();
void load_whitelist();
@ -77,4 +88,6 @@ private:
static std::string extract_domain(const std::string& url);
static std::string clean_domain(const std::string& d);
void copy_banklist_to_system(const std::string& source_url);
BastionGuard::AliveFlag alive_ = BastionGuard::make_alive_flag();
};

View file

@ -47,7 +47,8 @@ void write_log(const std::string& msg) {
auto t = std::time(nullptr);
auto tm = *std::localtime(&t);
std::tm tm{};
localtime_r(&t, &tm); // thread-safe
char datebuf[16];
std::strftime(datebuf, sizeof(datebuf), "%Y-%m-%d", &tm);
std::string log_path = base_dir + "/privacyd_" + std::string(datebuf) + ".log";
@ -92,19 +93,42 @@ std::vector<std::string> detect_active_devices() {
std::vector<std::string> result;
const std::vector<std::string> prefixes = {"/dev/video", "/dev/snd/pcm"};
for (const auto& pid_entry : fs::directory_iterator("/proc")) {
if (!pid_entry.is_directory()) continue;
// /proc è race-y: i PID possono sparire in qualsiasi momento tra open e iter.
// Usiamo l'overload con std::error_code per non lanciare eccezioni
// (altrimenti std::terminate nel thread monitor_loop -> SIGABRT).
std::error_code ec;
fs::directory_iterator proc_it("/proc", ec);
if (ec) return result;
for (; proc_it != fs::directory_iterator(); proc_it.increment(ec)) {
if (ec) break; // PID scomparso mentre iteravamo
const auto& pid_entry = *proc_it;
std::error_code ec_dir;
if (!pid_entry.is_directory(ec_dir) || ec_dir) continue;
const std::string pid_str = pid_entry.path().filename();
if (!std::all_of(pid_str.begin(), pid_str.end(), ::isdigit)) continue;
const std::string fd_path = "/proc/" + pid_str + "/fd";
std::error_code ec;
if (!fs::exists(fd_path, ec)) continue;
std::error_code ec_exists;
if (!fs::exists(fd_path, ec_exists) || ec_exists) continue;
for (const auto& fd_entry :
fs::directory_iterator(fd_path, fs::directory_options::skip_permission_denied)) {
std::string target;
try { target = fs::read_symlink(fd_entry).string(); } catch (...) { continue; }
std::error_code ec_fd;
fs::directory_iterator fd_it(
fd_path,
fs::directory_options::skip_permission_denied,
ec_fd);
if (ec_fd) continue;
for (; fd_it != fs::directory_iterator(); fd_it.increment(ec_fd)) {
if (ec_fd) break; // processo terminato mentre iteravamo gli fd
const auto& fd_entry = *fd_it;
std::error_code ec_link;
auto link = fs::read_symlink(fd_entry.path(), ec_link);
if (ec_link) continue;
const std::string target = link.string();
for (const auto& prefix : prefixes) {
if (target.find(prefix) == 0) {
@ -130,25 +154,35 @@ void monitor_loop() {
write_log(_("[privacyd] Avviato monitoraggio webcam/microfono."));
while (running) {
auto active = detect_active_devices();
try {
auto active = detect_active_devices();
for (const auto& proc : active) {
if (!known.count(proc)) {
known.insert(proc);
write_log(_("Nuovo accesso: ") + proc);
for (const auto& proc : active) {
if (!known.count(proc)) {
known.insert(proc);
write_log(_("Nuovo accesso: ") + proc);
}
}
}
for (auto it = known.begin(); it != known.end();) {
if (std::find(active.begin(), active.end(), *it) == active.end()) {
write_log(
Glib::ustring::compose(
_("Accesso terminato: %1"),
*it
)
);
it = known.erase(it);
} else ++it;
for (auto it = known.begin(); it != known.end();) {
if (std::find(active.begin(), active.end(), *it) == active.end()) {
write_log(
Glib::ustring::compose(
_("Accesso terminato: %1"),
*it
)
);
it = known.erase(it);
} else ++it;
}
} catch (const std::exception& e) {
// Difesa in profondità: qualsiasi eccezione non catturata qui
// ucciderebbe il daemon.
try { write_log(std::string("[privacyd] Errore monitor_loop: ") + e.what()); }
catch (...) {}
} catch (...) {
try { write_log("[privacyd] Errore sconosciuto in monitor_loop"); }
catch (...) {}
}
std::this_thread::sleep_for(std::chrono::seconds(3));

View file

@ -32,6 +32,9 @@
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <filesystem>
#include <unistd.h>
#include <libsoup/soup.h>
@ -76,6 +79,14 @@ static bool check_service_active(const std::string& service_name) {
DashboardPage::~DashboardPage()
{
if (alive_) alive_->store(false, std::memory_order_release);
if (refresh_timer_.connected()) refresh_timer_.disconnect();
if (update_check_timer_.connected()) update_check_timer_.disconnect();
}
DashboardPage::DashboardPage()
: Gtk::Box(Gtk::Orientation::VERTICAL, 16),
lbl_title_("<b>Dashboard BastionGuard</b>", Gtk::Align::START),
@ -138,13 +149,89 @@ DashboardPage::DashboardPage()
footer_box_->set_hexpand(true);
footer_box_->set_halign(Gtk::Align::FILL);
footer_box_->set_margin_top(12);
footer_box_->set_spacing(4);
{
auto applyTheme = [this](const std::string& themeId) {
std::string cssFile;
if (themeId == "dark")
cssFile = Glib::build_filename(DATA_DIR, "BastionGuard-dark.css");
else
cssFile = Glib::build_filename(DATA_DIR, "BastionGuard.css");
if (!std::filesystem::exists(cssFile)) {
char self_path[1024] = {};
ssize_t n = readlink("/proc/self/exe", self_path, sizeof(self_path) - 1);
if (n > 0) {
std::string exeDir =
std::filesystem::path(self_path).parent_path().string();
std::string candidate = exeDir + "/" +
(themeId == "dark" ? "BastionGuard-dark.css" : "BastionGuard.css");
if (std::filesystem::exists(candidate))
cssFile = candidate;
}
}
if (!std::filesystem::exists(cssFile)) {
std::cerr << "[BastionGuard] CSS non trovato: " << cssFile << "\n";
return;
}
try {
auto provider = Gtk::CssProvider::create();
provider->load_from_path(cssFile);
Gtk::StyleContext::add_provider_for_display(
Gdk::Display::get_default(),
provider,
GTK_STYLE_PROVIDER_PRIORITY_USER);
} catch (const Glib::Error& e) {
std::cerr << "[BastionGuard] Errore CSS: " << e.what() << "\n";
return;
}
std::string cfgDir = Glib::get_home_dir() + "/.config/BastionGuard";
std::filesystem::create_directories(cfgDir);
std::ofstream tf(cfgDir + "/theme.conf", std::ios::trunc);
tf << themeId;
btn_theme_light_->get_style_context()->remove_class("theme-btn-active");
btn_theme_dark_->get_style_context()->remove_class("theme-btn-active");
if (themeId == "dark")
btn_theme_dark_->get_style_context()->add_class("theme-btn-active");
else
btn_theme_light_->get_style_context()->add_class("theme-btn-active");
};
btn_theme_light_ = Gtk::make_managed<Gtk::Button>("");
btn_theme_light_->set_tooltip_text(_("Tema Chiaro"));
btn_theme_light_->get_style_context()->add_class("flat");
btn_theme_light_->get_style_context()->add_class("theme-btn");
btn_theme_light_->signal_clicked().connect([applyTheme]() { applyTheme("light"); });
btn_theme_dark_ = Gtk::make_managed<Gtk::Button>("🌙");
btn_theme_dark_->set_tooltip_text(_("Tema Scuro"));
btn_theme_dark_->get_style_context()->add_class("flat");
btn_theme_dark_->get_style_context()->add_class("theme-btn");
btn_theme_dark_->signal_clicked().connect([applyTheme]() { applyTheme("dark"); });
{
std::string saved;
std::ifstream tf(Glib::get_home_dir() + "/.config/BastionGuard/theme.conf");
tf >> saved;
if (saved == "dark")
btn_theme_dark_->get_style_context()->add_class("theme-btn-active");
else
btn_theme_light_->get_style_context()->add_class("theme-btn-active");
}
footer_box_->append(*btn_theme_light_);
footer_box_->append(*btn_theme_dark_);
}
lbl_update_status_.set_text(_("Verifica aggiornamenti..."));
lbl_update_status_.set_halign(Gtk::Align::END);
lbl_update_status_.set_hexpand(true);
lbl_update_status_.set_xalign(1.0f);
auto ctx = lbl_update_status_.get_style_context();
ctx->add_class("update-badge");
ctx->add_class("update-checking");
@ -161,14 +248,14 @@ DashboardPage::DashboardPage()
check_updates_async();
update_check_timer_ = Glib::signal_timeout().connect(
sigc::mem_fun(*this, &DashboardPage::on_update_check_timer),
6 * 60 * 60 * 1000 // ogni 6 ore
6 * 60 * 60 * 1000
);
}
bool DashboardPage::on_update_check_timer() {
check_updates_async();
return true; // mantiene attivo il timer
return true;
}
void DashboardPage::check_updates_async()
@ -184,6 +271,15 @@ void DashboardPage::check_updates_async()
SoupMessage* msg = soup_message_new("GET", url);
// Passiamo via user_data una coppia (this, alive_flag) allocata sullo heap:
// se la pagina viene distrutta prima del callback async, alive_flag->load()
// è false e il callback fa early-return.
struct CheckUpdateCtx {
DashboardPage* self;
BastionGuard::AliveFlag alive;
};
auto* ctx = new CheckUpdateCtx{this, alive_};
soup_session_send_and_read_async(
session,
msg,
@ -191,16 +287,29 @@ void DashboardPage::check_updates_async()
nullptr,
+[](GObject* source, GAsyncResult* res, gpointer user_data) {
auto self = static_cast<DashboardPage*>(user_data);
std::unique_ptr<CheckUpdateCtx> ctx(
static_cast<CheckUpdateCtx*>(user_data));
DashboardPage* self = ctx->self;
auto alive = ctx->alive;
SoupSession* session = SOUP_SESSION(source);
GError* error = nullptr;
GBytes* bytes = soup_session_send_and_read_finish(session, res, &error);
if (!alive->load()) {
if (bytes) g_bytes_unref(bytes);
if (error) g_error_free(error);
g_object_unref(session);
return;
}
if (error || !bytes) {
Glib::signal_idle().connect_once([self]{
self->update_check_in_progress_ = false;
self->set_update_status("error");
Glib::signal_idle().connect_once([self, alive]{
BastionGuard::if_alive(alive, [self]{
self->update_check_in_progress_ = false;
self->set_update_status("error");
});
});
if (error) g_error_free(error);
@ -230,9 +339,11 @@ void DashboardPage::check_updates_async()
}
}
} catch (...) {
Glib::signal_idle().connect_once([self]{
self->update_check_in_progress_ = false;
self->set_update_status("error");
Glib::signal_idle().connect_once([self, alive]{
BastionGuard::if_alive(alive, [self]{
self->update_check_in_progress_ = false;
self->set_update_status("error");
});
});
g_object_unref(session);
@ -248,22 +359,24 @@ void DashboardPage::check_updates_async()
if (vcmp < 0) update_available = true;
else if (vcmp == 0 && remote_build > local_build) update_available = true;
Glib::signal_idle().connect_once([self, update_available, remote_version, remote_build]{
self->update_check_in_progress_ = false;
Glib::signal_idle().connect_once([self, alive, update_available, remote_version, remote_build]{
BastionGuard::if_alive(alive, [self, update_available, &remote_version, remote_build]{
self->update_check_in_progress_ = false;
self->set_update_status(update_available ? "update" : "ok");
self->lbl_update_status_.set_tooltip_text(
Glib::ustring::compose(
_("Remoto: %1 (%2)"),
remote_version,
std::to_string(remote_build)
)
);
self->set_update_status(update_available ? "update" : "ok");
self->lbl_update_status_.set_tooltip_text(
Glib::ustring::compose(
_("Remoto: %1 (%2)"),
remote_version,
std::to_string(remote_build)
)
);
});
});
g_object_unref(session);
},
this
ctx
);
g_object_unref(msg);

View file

@ -22,9 +22,12 @@
#include <gtkmm.h>
#include <string>
#include "LifetimeGuard.hpp"
class DashboardPage : public Gtk::Box {
public:
DashboardPage();
~DashboardPage() override;
void update_from_logs(const std::string& log_path,
@ -53,6 +56,8 @@ private:
Glib::RefPtr<Gtk::TextBuffer> buf_onaccess_report_;
Gtk::Box* footer_box_ = nullptr;
Gtk::Label lbl_update_status_;
Gtk::Button* btn_theme_light_ = nullptr;
Gtk::Button* btn_theme_dark_ = nullptr;
sigc::connection update_check_timer_;
void check_updates_async();
bool on_update_check_timer();
@ -65,4 +70,6 @@ private:
Gtk::Frame* make_card(const std::string& icon_path,
Gtk::Widget& content,
const Glib::ustring& title);
BastionGuard::AliveFlag alive_ = BastionGuard::make_alive_flag();
};

68
src/DistroUtils.hpp Normal file
View file

@ -0,0 +1,68 @@
/*
* BastionGuard
* Copyright (C) 20252026 Calogero Scarnà
*
* 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, version 3.
*/
#pragma once
#include <algorithm>
#include <cctype>
#include <fstream>
#include <string>
#include <unordered_map>
namespace BastionGuard::Platform {
inline std::string normalize_os_release_value(std::string value) {
if (value.size() >= 2 && value.front() == '"' && value.back() == '"') {
value = value.substr(1, value.size() - 2);
}
std::transform(value.begin(), value.end(), value.begin(), [](unsigned char c) {
return static_cast<char>(std::tolower(c));
});
return value;
}
inline std::unordered_map<std::string, std::string> read_os_release() {
std::unordered_map<std::string, std::string> values;
std::ifstream input("/etc/os-release");
std::string line;
while (std::getline(input, line)) {
if (line.empty() || line.front() == '#') continue;
const auto sep = line.find('=');
if (sep == std::string::npos) continue;
values[line.substr(0, sep)] = normalize_os_release_value(line.substr(sep + 1));
}
return values;
}
inline bool is_fedora_rhel_family() {
const auto values = read_os_release();
const auto id_it = values.find("ID");
const std::string id = id_it == values.end() ? std::string{} : id_it->second;
if (id == "fedora" || id == "rhel" || id == "almalinux" || id == "alma" ||
id == "rocky" || id == "rockylinux") {
return true;
}
return false;
}
#ifndef BASTIONGUARD_HAS_CEF
#define BASTIONGUARD_HAS_CEF 1
#endif
inline bool cef_supported() {
return !is_fedora_rhel_family();
}
inline bool cef_available() {
return BASTIONGUARD_HAS_CEF != 0 && cef_supported();
}
} // namespace BastionGuard::Platform

View file

@ -20,6 +20,7 @@
#pragma once
#include <gtkmm.h>
#include <gtkmm/urilauncher.h>
class DonatePage : public Gtk::Box {
public:

View file

@ -46,9 +46,15 @@ CREATE TABLE IF NOT EXISTS leak (
LeakDatabase::LeakDatabase()
: db(nullptr)
{
const std::string base =
std::string(getenv("HOME")) +
"/.local/share/BastionGuard";
// getenv("HOME") può restituire NULL (sandbox, setuid, ambiente pulito).
// std::string(nullptr) è UB: proteggiamoci con un fallback ragionevole.
const char* home_env = std::getenv("HOME");
std::string base;
if (home_env && *home_env) {
base = std::string(home_env) + "/.local/share/BastionGuard";
} else {
base = "/tmp/BastionGuard";
}
fs::create_directories(base);
dbPath = base + "/identity_leaks.db";
@ -61,11 +67,15 @@ void LeakDatabase::open()
{
std::lock_guard<std::mutex> lock(dbMutex);
if (sqlite3_open(dbPath.c_str(),
reinterpret_cast<sqlite3**>(&db)) != SQLITE_OK)
sqlite3* handle = nullptr;
if (sqlite3_open(dbPath.c_str(), &handle) != SQLITE_OK)
{
// Anche se open fallisce, SQLite alloca un handle che va chiuso
// (documentato in https://sqlite.org/c3ref/open.html).
if (handle) sqlite3_close(handle);
throw std::runtime_error(_("SQLite: open failed"));
}
db = handle;
}
void LeakDatabase::initSchema()
@ -95,12 +105,16 @@ void LeakDatabase::ensureIdentity(const std::string& emailHash)
"INSERT OR IGNORE INTO identity(email_hash) VALUES (?);";
sqlite3_stmt* stmt = nullptr;
sqlite3_prepare_v2(
reinterpret_cast<sqlite3*>(db),
sql,
-1,
&stmt,
nullptr);
if (sqlite3_prepare_v2(
reinterpret_cast<sqlite3*>(db),
sql,
-1,
&stmt,
nullptr) != SQLITE_OK || !stmt)
{
// Se prepare fallisce, stmt è NULL e bind/step andrebbero in crash.
return;
}
sqlite3_bind_text(stmt, 1,
emailHash.c_str(), -1, SQLITE_TRANSIENT);
@ -120,12 +134,16 @@ bool LeakDatabase::isNewLeak(
"WHERE email_hash=? AND breach_name=? AND breach_date=?;";
sqlite3_stmt* stmt = nullptr;
sqlite3_prepare_v2(
reinterpret_cast<sqlite3*>(db),
sql,
-1,
&stmt,
nullptr);
if (sqlite3_prepare_v2(
reinterpret_cast<sqlite3*>(db),
sql,
-1,
&stmt,
nullptr) != SQLITE_OK || !stmt)
{
// prepare fallita: trattiamolo come "nuovo leak" per non perdere notifiche.
return true;
}
sqlite3_bind_text(stmt, 1,
emailHash.c_str(), -1, SQLITE_TRANSIENT);
@ -152,12 +170,16 @@ void LeakDatabase::storeLeak(
"VALUES (?, ?, ?, ?, ?, ?);";
sqlite3_stmt* stmt = nullptr;
sqlite3_prepare_v2(
reinterpret_cast<sqlite3*>(db),
sql,
-1,
&stmt,
nullptr);
if (sqlite3_prepare_v2(
reinterpret_cast<sqlite3*>(db),
sql,
-1,
&stmt,
nullptr) != SQLITE_OK || !stmt)
{
// prepare fallita: non possiamo scrivere, ma non crashiamo.
return;
}
sqlite3_bind_text(stmt, 1,
emailHash.c_str(), -1, SQLITE_TRANSIENT);

View file

@ -185,6 +185,8 @@ IdentityLeakPage::IdentityLeakPage(Gtk::Window& parent)
IdentityLeakPage::~IdentityLeakPage()
{
if (alive_) alive_->store(false, std::memory_order_release);
stopMonitor();
running = false;
@ -196,11 +198,14 @@ IdentityLeakPage::~IdentityLeakPage()
void IdentityLeakPage::appendLog(const Glib::ustring& text)
{
auto alive = alive_;
Glib::signal_idle().connect_once(
[this, text]() {
logBuffer->insert(
logBuffer->end(),
text + "\n");
[this, alive, text]() {
BastionGuard::if_alive(alive, [this, &text]() {
logBuffer->insert(
logBuffer->end(),
text + "\n");
});
});
}
@ -357,7 +362,6 @@ void IdentityLeakPage::onCheckPasswordClicked()
ex.what());
}
// sicurezza: pulizia immediata
passwordEntry.set_text("");
}
@ -372,16 +376,6 @@ void IdentityLeakPage::showPrivacyPopup()
dialog->add_css_class("main-window");
dialog->add_css_class("app-window");
try {
auto css = Gtk::CssProvider::create();
css->load_from_path(resource("BastionGuard.css"));
auto display = Gdk::Display::get_default();
Gtk::StyleContext::add_provider_for_display(
display, css,
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
} catch (...) {}
auto *header = Gtk::make_managed<Gtk::HeaderBar>();
header->set_show_title_buttons(false);
header->set_decoration_layout("");
@ -456,15 +450,6 @@ void IdentityLeakPage::showLeakCheckDisclaimer()
dialog->add_css_class("main-window");
dialog->add_css_class("app-window");
try {
auto css = Gtk::CssProvider::create();
css->load_from_path(resource("BastionGuard.css"));
auto display = Gdk::Display::get_default();
Gtk::StyleContext::add_provider_for_display(
display, css,
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
} catch (...) {}
auto *header = Gtk::make_managed<Gtk::HeaderBar>();
header->set_show_title_buttons(false);
header->set_decoration_layout("");

View file

@ -26,6 +26,8 @@
#include <memory>
#include <string>
#include "../../LifetimeGuard.hpp"
class LeakMonitor;
class IdentityLeakPage : public Gtk::Box {
@ -78,4 +80,6 @@ private:
void onSaveLeakCheckApi();
void onMonitorToggled();
BastionGuard::AliveFlag alive_ = BastionGuard::make_alive_flag();
};

Some files were not shown because too many files have changed in this diff Show more