1. Component role
This file is a core component of the BastionGuard Wizard. It implements the primary GTK-based wizard window that drives the initial system configuration, collects user choices, and orchestrates privileged and non-privileged setup steps in a controlled sequence.
In practical terms, the Wizard Window provides:
- a step-by-step UI (welcome → resolver → firewall → nftables → certificates → webserver → native host → user agent → banks → summary);
- toggle-based selection of setup actions;
- centralized logging into a GUI log view with timestamps;
- a worker-thread execution model to keep the UI responsive;
- a “single authentication” strategy for privileged operations, to avoid multiple password prompts.
2. Privilege handling and single authentication strategy
2.1 Root-session tracking
The global flag g_wizard_root_session_started is used as an internal indicator that an elevated session has already been initiated. When it is set, subsequent privileged operations can be executed without re-triggering Polkit authentication logic in the helper wrapper.
2.2 Safe quoting for shell execution
The helper shell_quote() escapes strings to be safely embedded in shell commands. This is critical because the Wizard dynamically builds commands that include file paths and user-provided values (e.g., web ports, extension IDs, script paths).
2.3 elev_cmd wrapper
elev_cmd(inner, action_id) is the Wizard’s central privilege wrapper:
- If the process is already running as root (
geteuid()==0) or the wizard session is marked as started, it runs/bin/bash -cdirectly. - Otherwise it prefers
pkexec(Polkit), using--action-idwhen supported, and falls back tosudo.
This ensures compatibility across Polkit versions and distributions while reducing repeated prompts.
3. Wizard window UI structure
3.1 Navigation model
The Wizard uses:
- a left sidebar of step buttons (
Gtk::ToggleButton) for direct navigation; - a central stack (
m_stack) holding each page widget; - a right-side navigation panel with Back/Next/Finish/Cancel.
Navigation state is controlled by:
set_page(idx): updates the visible page in the stack and the active sidebar button;update_nav(): enables/disables buttons depending on the current step and whether the wizard is running;on_next(),on_back(),on_finish(),on_cancel(): event handlers wired to UI buttons.
3.2 Pages and user options
The constructor sets up a sequence of pages, each representing a setup domain:
- Resolver: enables local DNS resolver integration (
127.0.0.1), plus browser DoH policies. - Firewall: opens required ports and adjusts user group memberships for log access.
- Advanced Firewall (nftables): optional installation and activation if no other firewall is active.
- Certificates: creates a local CA and server certificate and installs the CA into the OS trust store.
- Webserver: configures nginx ports and vhost templates; includes distro selection and port entry fields.
- Native Host: installs browser Native Messaging Host manifests (user-level) for extension integration.
- User Agent: enables user-agent services for active users, with a “Run now” action.
- Banks list (MISP): downloads the official bank warning list JSON to the user’s data directory.
- Summary: generates and displays a final selection overview and execution log.
4. Logging and UI responsiveness
4.1 Thread-safe GUI logging
Logging is implemented using:
- a mutex-protected queue (
m_log_queue); - a GTK dispatcher (
m_dispatcher) that flushes queued log lines into aGtk::TextBufferon the main thread; - timestamping for each log entry (
[HH:MM:SS]).
This prevents UI thread violations while allowing background worker tasks to emit progress messages.
4.2 Background execution
The wizard executes long-running work in m_worker, a dedicated std::thread created by start_execution(). This keeps the UI responsive during system configuration.
Completion is signaled through m_done_dispatcher, which calls finish_execution(m_result_ok) on the main thread.
5. Execution pipeline and sequencing
5.1 on_finish(): pre-steps and orchestration
When the user clicks Execute:
- The wizard writes a persistent config marker (
config.json) indicating the wizard was completed. - If selected, it enables the User Agent service immediately.
- If selected and no firewall is active, it installs nftables configuration.
- It runs the network setup script
BastionGuard-net-setup.sh(via pkexec subprocess) before the main privileged batch. - If selected, it downloads the MISP banks list at user-level (no admin rights).
- Finally it starts the main combined execution flow (
start_execution()→worker_run()).
5.2 start_execution(): pre-authentication
start_execution() implements a “pre-auth” step by running pkexec /bin/true once. This warms up Polkit authentication and reduces friction during subsequent privileged operations.
5.3 worker_run(): combined privileged batch
worker_run() assembles a command list (cmds) and executes it in one elevated script using run_all_elevated_steps(). This is the primary “single prompt” mechanism.
Notable ordering rules:
- Absolute pre-step: ClamAV daemon setup is inserted first and treated as critical.
- Locale pre-step: the locale generation script (
en_US.UTF-8) runs early to prevent locale-related failures later. - Selected steps: resolver override, firewall rules, certificates, and webserver config are appended based on toggles.
- Service restart: the phishing scanner service is restarted at the end of the privileged batch (best-effort).
5.4 Post privileged batch
After privileged steps complete, user-level tasks can still run:
- Native Messaging Host installation (user-level manifests) is executed after the privileged batch.
6. Key setup tasks implemented by this component
6.1 Browser DoH policy configuration
configure_browser_doh() installs policies for:
- Firefox via
/usr/lib/firefox/distribution/policies.json - Chromium-based browsers via managed policy JSON under
/etc
If not running as root, it writes a temporary file and installs it using an elevated install -m 644 command invoked through elev_cmd().
6.2 NGINX web configuration
The wizard supports:
- detecting nginx presence;
- reading current
listenports from common nginx config locations; - generating config files from packaged templates with placeholder substitution;
- applying changes through an elevated temporary script, followed by
nginx -tand a service restart.
6.3 MISP banks list download
download_bank_list_user() fetches the MISP warning list JSON via curl and saves it to:
~/.local/share/BastionGuard/banks.json
This step explicitly avoids requiring administrative privileges.
7. Completion and user feedback
finish_execution() presents a final GTK dialog:
- success: confirmation plus guidance (e.g., browser restart for Native Host);
- failure: warning dialog advising the user to inspect the log output.
In both cases, it emits m_signal_finished to notify the rest of the application that the wizard flow ended.