chore(release): v0.7.5

Corrige l'échec silencieux « Accès refusé » à la connexion Windows :
wireguard.exe /install|uninstalltunnelservice était lancé sans élévation
en misant sur son manifeste UAC natif, qui ne s'auto-déclenche jamais via
un appel process-à-process. L'appel tente maintenant sans élévation
(compatible avec les ACLs accordées via le bouton dédié), puis retente
avec une vraie élévation UAC si le premier essai échoue. Le diagnostic
d'élévation est mis à jour pour refléter les deux cas.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 14:24:56 +02:00
co-authored by Claude Sonnet 5
parent 3b869aeae8
commit 66faf5e661
7 changed files with 45 additions and 20 deletions
+8
View File
@@ -6,6 +6,14 @@ Ce projet suit le [Versionnage Sémantique](https://semver.org/lang/fr/).
--- ---
## [0.7.5] — 2026-09-04
### Corrigé
- **Connexion Windows en échec silencieux sur « Accès refusé ».** `wireguard.exe /installtunnelservice` et `/uninstalltunnelservice` étaient lancés sans élévation en misant sur le manifeste UAC natif de `wireguard.exe` — qui ne s'auto-déclenche que lancé depuis l'explorateur ou via ShellExecute, jamais via l'appel process-à-process utilisé ici. Sans les ACLs du service accordées, la connexion échouait donc directement, sans jamais afficher la moindre invite. L'appel tente maintenant d'abord sans élévation (aucune UAC si les ACLs ont été accordées via le bouton dédié), puis retente avec une véritable élévation UAC (`ShellExecuteEx "runas"`) si le premier essai échoue.
- **Diagnostic d'élévation Windows trompeur.** Le panneau Tests & diagnostic annonçait qu'une invite UAC apparaîtrait à chaque connexion sans mentionner que les ACLs accordées au service l'évitent — corrigé pour refléter les deux cas.
---
## [0.7.4] — 2026-09-04 ## [0.7.4] — 2026-09-04
### Ajouté ### Ajouté
+1 -1
View File
@@ -4,7 +4,7 @@
## ────────────────────────────────────────────── ## ──────────────────────────────────────────────
APP := wgsecure APP := wgsecure
VERSION := 0.7.4 VERSION := 0.7.5
VENV := .venv VENV := .venv
PYTHON := $(VENV)/bin/python3 PYTHON := $(VENV)/bin/python3
PIP := $(VENV)/bin/pip PIP := $(VENV)/bin/pip
+2 -2
View File
@@ -1,6 +1,6 @@
# 🛡️ WGSecure (WGS) # 🛡️ WGSecure (WGS)
🚀 v0.7.4 · 🐍 · 🪟🐧 · 🔐 MFA TOTP · 🛡️ WireGuard 🚀 v0.7.5 · 🐍 · 🪟🐧 · 🔐 MFA TOTP · 🛡️ WireGuard
**WGSecure** est une interface graphique multiplateforme (Windows & Linux) pour gérer une connexion WireGuard avec une surcouche MFA (authentification à deux facteurs TOTP). **WGSecure** est une interface graphique multiplateforme (Windows & Linux) pour gérer une connexion WireGuard avec une surcouche MFA (authentification à deux facteurs TOTP).
@@ -210,4 +210,4 @@ WGSecure/
## 👤 Auteur ## 👤 Auteur
Développé par **Johnny** — [JT-Tools](https://github.com/JT-Tools) Développé par **Johnny** — [JT-Tools](https://github.com/JT-Tools)
Version : ![v0.7.4](https://img.shields.io/badge/v0.7.4-septembre%202026-2980b9?style=flat-square) — Septembre 2026 Version : ![v0.7.5](https://img.shields.io/badge/v0.7.5-septembre%202026-2980b9?style=flat-square) — Septembre 2026
+1 -1
View File
@@ -1,3 +1,3 @@
__version__ = "0.7.4" __version__ = "0.7.5"
APP_NAME = "WGSecure" APP_NAME = "WGSecure"
APP_SHORT = "WGS" APP_SHORT = "WGS"
+23 -8
View File
@@ -213,6 +213,27 @@ def interface_exists(cfg: Config) -> bool:
return dns_util.interface_exists(cfg.wg.get("interface_name", "wgs0")) return dns_util.interface_exists(cfg.wg.get("interface_name", "wgs0"))
def _run_wireguard_service_cmd(cmd: list[str], timeout: int) -> tuple[int, str, str]:
"""Lance `wireguard.exe /install…` ou `/uninstall…tunnelservice`.
Un utilisateur dont les ACLs du service ont été accordées (bouton
« Configurer les permissions » du panneau Admin) peut créer/supprimer ses
tunnels sans élévation : l'appel non privilégié est donc tenté en premier,
pour ne jamais déclencher d'UAC inutile dans ce cas.
Sans ACL accordée, cet appel échoue sur « Accès refusé » — le manifeste
UAC de wireguard.exe ne s'applique que lancé depuis l'explorateur ou via
ShellExecute, jamais via CreateProcess (`run_command`) — et échouait donc
silencieusement plutôt que de demander l'élévation. On retente alors via
`run_privileged`, seul à passer par ShellExecuteEx "runas" pour obtenir une
vraie invite UAC.
"""
code, out, err = run_command(cmd, timeout)
if code == 0:
return code, out, err
return run_privileged(cmd, timeout)
def force_cleanup(cfg: Config) -> list[str]: def force_cleanup(cfg: Config) -> list[str]:
"""Démonte tout résidu du tunnel : entrée DNS orpheline + interface morte. """Démonte tout résidu du tunnel : entrée DNS orpheline + interface morte.
@@ -229,10 +250,9 @@ def force_cleanup(cfg: Config) -> list[str]:
if is_windows(): if is_windows():
# Le service du tunnel restaure routes et DNS en s'arrêtant. # Le service du tunnel restaure routes et DNS en s'arrêtant.
# Sous Windows, wireguard.exe gère lui-même l'élévation via son manifeste UAC.
if dns_util.interface_exists(name): if dns_util.interface_exists(name):
cmd = [wireguard_exe(), "/uninstalltunnelservice", name] cmd = [wireguard_exe(), "/uninstalltunnelservice", name]
run_command(cmd, timeout=60) _run_wireguard_service_cmd(cmd, timeout=60)
# Nettoyer les règles split-DNS # Nettoyer les règles split-DNS
dns_util.cleanup_split_dns(cfg) dns_util.cleanup_split_dns(cfg)
actions += dns_util.cleanup(name) actions += dns_util.cleanup(name)
@@ -305,13 +325,8 @@ def connect(cfg: Config) -> tuple[bool, str]:
return True, "Tunnel WireGuard déjà actif" return True, "Tunnel WireGuard déjà actif"
if dns_util.interface_exists(name): if dns_util.interface_exists(name):
force_cleanup(cfg) force_cleanup(cfg)
# Sous Windows, wireguard.exe gère lui-même l'élévation via son manifeste UAC.
# Sous Linux, wg-quick nécessite sudo.
cmd = [wireguard_exe(), "/installtunnelservice", result] cmd = [wireguard_exe(), "/installtunnelservice", result]
if is_windows(): code, _, err = _run_wireguard_service_cmd(cmd, timeout=90)
code, _, err = run_command(cmd, timeout=90)
else:
code, _, err = run_privileged(cmd, timeout=90)
# /installtunnelservice enregistre le service et rend la main : le # /installtunnelservice enregistre le service et rend la main : le
# démarrage effectif du tunnel est asynchrone. Tester l'état # démarrage effectif du tunnel est asynchrone. Tester l'état
# immédiatement conclurait « échec » sur un tunnel qui monte. # immédiatement conclurait « échec » sur un tunnel qui monte.
+9 -7
View File
@@ -1776,14 +1776,16 @@ class AdminWindow(QDialog):
"fenêtre UAC à la connexion.") "fenêtre UAC à la connexion.")
state = "ok" state = "ok"
else: else:
lines.append("⚠️ Processus non élevé : Windows demandera une " lines.append("⚠️ Processus non élevé : si les permissions ACL du "
"confirmation UAC à chaque") "service n'ont pas été")
lines.append(" connexion et déconnexion du tunnel.") lines.append(" accordées (bouton ci-dessous), Windows "
"demandera une confirmation UAC")
lines.append(" à chaque connexion et déconnexion du tunnel.")
lines.append("") lines.append("")
lines.append("Pour l'éviter : lancez WGSecure via un raccourci " lines.append("Pour l'éviter : accordez les permissions ACL, ou "
"coché « Exécuter en tant") "lancez WGSecure via un")
lines.append("qu'administrateur », ou une tâche planifiée avec " lines.append("raccourci coché « Exécuter en tant "
"les privilèges les plus élevés.") "qu'administrateur ».")
state = "warn" state = "warn"
lines.append("") lines.append("")
+1 -1
View File
@@ -5,7 +5,7 @@
; ────────────────────────────────────────────── ; ──────────────────────────────────────────────
#define MyAppName "WGSecure" #define MyAppName "WGSecure"
#define MyAppVersion "0.7.4" #define MyAppVersion "0.7.5"
#define MyAppPublisher "WGSecure" #define MyAppPublisher "WGSecure"
#define MyAppExeName "wgsecure.exe" #define MyAppExeName "wgsecure.exe"