PacManager

1. Overview

PacManager is the desktop-integration layer responsible for enabling and disabling BastionGuard’s Secure Payments PAC configuration on the host system. It orchestrates two distinct responsibilities:

  • Lifecycle management of the bastionguard-pacd daemon as a systemd --user service.
  • Proxy/PAC configuration on common Linux desktop environments (GNOME, KDE, XFCE), with a headless fallback via environment.d.

The implementation follows a best-effort strategy: it attempts configuration backends in a fixed priority order and returns the first successful result, while preserving a clear status message describing what backend was used and whether the operation succeeded.


2. Responsibilities and Integration Points

  • systemd (user scope) – start/stop/enable/disable bastionguard-pacd.service.
  • GNOME – configure proxy mode and PAC URL via gsettings.
  • KDE Plasma – configure PAC via kioslaverc and preferably kwriteconfig6.
  • XFCE – configure proxy/PAC via xfconf-query.
  • Headless fallback – configure classic proxy environment variables using ~/.config/environment.d.

It indirectly supports the Secure Payments stack by ensuring the browser retrieves and uses the PAC file exposed by bastionguard-pacd, and that proxy routing is correctly applied for payment domains.


3. Public API and Result Model

PacManager returns a structured result:

  • ok – success flag
  • backend – which backend was used (systemd-user, gnome, kde, xfce, env)
  • message – human-readable diagnostics

Primary entry points:

  • enable_pac(pac_url) – configure the desktop to use the given PAC URL.
  • disable_pac() – revert proxy settings to “none” (or remove fallback).
  • enable_pac_with_pacd(pac_url) – start pacd, then enable PAC in the desktop environment.
  • disable_pac_with_pacd() – disable PAC, then stop pacd.

4. Command Execution Utilities

4.1 cmd_exists()

Checks availability of commands using:

command -v <cmd> >/dev/null 2>&1

This is used to detect whether systemctl, gsettings, kwriteconfig6, or xfconf-query are usable on the current system.


4.2 run_cmd()

Runs a shell command via popen() and optionally captures stdout. The return code is obtained via pclose(). This helper is used primarily for GNOME (gsettings) to set keys and capture potential output for troubleshooting.


5. systemd –user Integration (pacd lifecycle)

5.1 start_pacd_user()

Starts the PAC daemon as a user service using a best-effort sequence:

  1. systemctl --user daemon-reload
  2. systemctl --user enable --now bastionguard-pacd.service

If both operations succeed, the result is marked successful and the backend is set to systemd-user.


5.2 stop_pacd_user()

Stops and disables the service (best-effort):

systemctl --user disable --now bastionguard-pacd.service

This function returns success even if stop/disable fails, because disabling PAC configuration is the more important user-facing action. This is consistent with the overall best-effort strategy.


6. Desktop PAC Enable/Disable Orchestration

6.1 enable_pac(pac_url)

Attempts desktop backends in this exact order:

  1. GNOME (enable_gnome)
  2. KDE (enable_kde)
  3. XFCE (enable_xfce)
  4. Headless fallback (enable_env_fallback)

The function returns immediately on first successful backend. If all desktop backends fail, the environment fallback is applied.


6.2 disable_pac()

Uses the same backend priority order to revert proxy settings:

  1. GNOME (disable_gnome)
  2. KDE (disable_kde)
  3. XFCE (disable_xfce)
  4. Headless fallback (disable_env_fallback)

7. GNOME Backend (gsettings)

7.1 Enable (PAC mode)

Requires gsettings. It configures:

  • org.gnome.system.proxy mode = 'auto'
  • org.gnome.system.proxy autoconfig-url = <pac_url>

Commands executed:

gsettings set org.gnome.system.proxy mode 'auto'
gsettings set org.gnome.system.proxy autoconfig-url '<PAC_URL>'

The PAC URL is shell-quoted using Glib::shell_quote() to reduce injection risk in the GNOME path.


7.2 Disable

Reverts GNOME proxy mode to none:

gsettings set org.gnome.system.proxy mode 'none'

8. KDE Backend (kioslaverc / kwriteconfig6)

8.1 Target File

The KDE proxy configuration is written into:

~/.config/kioslaverc

8.2 Enable (preferred path: kwriteconfig6)

If kwriteconfig6 exists, PacManager writes in the [Proxy Settings] group:

  • ProxyType=2 (commonly PAC mode)
  • AutoConfigScript=<PAC_URL>

Example behavior:

kwriteconfig6 --file "~/.config/kioslaverc" --group "Proxy Settings" --key ProxyType 2
kwriteconfig6 --file "~/.config/kioslaverc" --group "Proxy Settings" --key AutoConfigScript "<PAC_URL>"

8.3 Enable (fallback: direct file manipulation)

If kwriteconfig6 is unavailable or fails, PacManager performs a simple text rewrite strategy:

  • Loads existing content (if any)
  • Removes any existing [Proxy Settings] block (best-effort pattern)
  • Appends a new [Proxy Settings] block with PAC values

This fallback is pragmatic and minimizes dependencies, but it is not a fully semantic INI editor.


8.4 Disable

Disables proxy by setting:

  • ProxyType=0 (no proxy)

Preferred path uses kwriteconfig6; fallback modifies the first occurrence of ProxyType= (or appends a minimal block if absent).


9. XFCE Backend (xfconf-query)

9.1 Enable

Requires xfconf-query. PacManager writes to channel xfce4-settings-manager:

  • /proxy/mode = 2 (intended as “auto/PAC” mode; may vary across distro setups)
  • /proxy/autoconfig-url = <PAC_URL>

Commands executed:

xfconf-query -c xfce4-settings-manager -p /proxy/mode -s 2
xfconf-query -c xfce4-settings-manager -p /proxy/autoconfig-url -s "<PAC_URL>"

Because XFCE proxy keys can differ across distributions, the failure message explicitly notes that channel/properties may vary.


9.2 Disable

Reverts XFCE proxy mode to none:

xfconf-query -c xfce4-settings-manager -p /proxy/mode -s 0

10. Headless Fallback (systemd environment.d)

10.1 Purpose and Limitations

If no desktop backend is applicable, PacManager falls back to setting classic proxy environment variables. This does not implement PAC logic at the environment level; instead it points HTTP(S) traffic to a local proxy endpoint.

This is intended for headless sessions or environments where desktop proxy configuration tools are absent. It typically requires relogin or session restart to take effect.


10.2 Target File

The fallback writes to:

~/.config/environment.d/90-bastionguard-proxy.conf

10.3 Enable

Writes the following keys:

http_proxy=http://127.0.0.1:3129
https_proxy=http://127.0.0.1:3129
HTTP_PROXY=http://127.0.0.1:3129
HTTPS_PROXY=http://127.0.0.1:3129

Note: the chosen port (3129) matches the Secure Payments stub proxy in the default pacd configuration and must remain consistent with your deployment.


10.4 Disable

Removes the environment.d file if it exists. This is a clean revert strategy and avoids leaving stale proxy variables across sessions.


11. Combined Operations (PAC + pacd)

11.1 enable_pac_with_pacd(pac_url)

Provides a single entry point to fully enable Secure Payments routing:

  1. Start bastionguard-pacd via systemd user service
  2. Enable PAC configuration using the best available desktop backend

If pacd fails to start, the function returns immediately, preventing a partially-enabled state where the desktop points to a PAC URL that is not served.


11.2 disable_pac_with_pacd()

Performs the reverse sequence:

  1. Disable PAC configuration first (revert desktop proxy state)
  2. Stop pacd service (best-effort)

This sequencing prioritizes restoring system network behavior even if pacd stop fails.


12. Security and Operational Considerations

  • Shell execution surface: multiple operations rely on system() / popen(). GNOME PAC URL is quoted; KDE fallback writes raw text; XFCE uses quoted PAC URL. Ensure the PAC URL is always application-controlled or strictly validated.
  • Desktop variability: KDE and XFCE keys can differ across versions; PacManager includes fallbacks but may require per-distro tuning for perfect coverage.
  • Session applicability: environment.d fallback typically requires relogin/session restart to apply.
  • Port coherence: the fallback hardcodes 127.0.0.1:3129. Keep it aligned with pacd stub proxy configuration and the Secure Payments architecture.
  • Observability: the returned Result provides backend + message, enabling the UI layer to show actionable diagnostics to the user.

13. Typical Secure Payments Activation Flow

  1. User enables Secure Payments in Settings.
  2. Application calls PacManager::enable_pac_with_pacd("http://127.0.0.1:8765/proxy.pac").
  3. pacd is enabled and started via systemctl --user.
  4. Desktop proxy settings are updated (GNOME/KDE/XFCE), pointing to the PAC URL.
  5. Browser downloads the PAC file and routes payment domains via stub proxy.
  6. Stub proxy triggers the CEF backend service on first payment-domain connection.