chore(release): v0.7.16

Durcit la boucle principale de wgsecure-helper : ne capturait que
pywintypes.error (pas Exception en général) et ne protégeait pas
CloseHandle individuellement dans le nettoyage, si bien qu'une
exception inattendue sur une requête pouvait arrêter tout le
service — expliquant un premier échange réussi (juste après
démarrage) puis un service injoignable ensuite. Gère aussi
ERROR_PIPE_CONNECTED (course normale, pas rare, entre CreateNamedPipe
et ConnectNamedPipe) au lieu de la traiter comme une erreur.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 21:50:57 +02:00
co-authored by Claude Sonnet 5
parent 5133868951
commit b4f85c5605
6 changed files with 57 additions and 19 deletions
+7
View File
@@ -6,6 +6,13 @@ Ce projet suit le [Versionnage Sémantique](https://semver.org/lang/fr/).
--- ---
## [0.7.16] — 2026-09-04
### Corrigé
- **Le service `wgsecure-helper` répondait au premier appel puis devenait injoignable** (connexion automatique au démarrage sans prompt, puis retour aux invites UAC ensuite). La boucle principale ne capturait que `pywintypes.error` et ne protégeait pas `CloseHandle` individuellement dans son nettoyage — une exception non prévue sur une requête, ou un échec de fermeture de handle, pouvait faire sortir de la boucle et arrêter tout le service. Chaque étape (création du pipe, connexion, traitement, fermeture) est désormais individuellement protégée par une capture large, avec un filet de sécurité final qui journalise toute erreur inattendue au lieu de laisser le service disparaître en silence. Gère aussi correctement `ERROR_PIPE_CONNECTED` (client connecté entre la création du pipe et l'appel `ConnectNamedPipe` — un cas normal, pas rare, qui faisait auparavant rater la requête).
---
## [0.7.15] — 2026-09-04 ## [0.7.15] — 2026-09-04
### Corrigé ### Corrigé
+1 -1
View File
@@ -4,7 +4,7 @@
## ────────────────────────────────────────────── ## ──────────────────────────────────────────────
APP := wgsecure APP := wgsecure
VERSION := 0.7.15 VERSION := 0.7.16
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.15 · 🐍 · 🪟🐧 · 🔐 MFA TOTP · 🛡️ WireGuard 🚀 v0.7.16 · 🐍 · 🪟🐧 · 🔐 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.15](https://img.shields.io/badge/v0.7.15-septembre%202026-2980b9?style=flat-square) — Septembre 2026 Version : ![v0.7.16](https://img.shields.io/badge/v0.7.16-septembre%202026-2980b9?style=flat-square) — Septembre 2026
+1 -1
View File
@@ -1,3 +1,3 @@
__version__ = "0.7.15" __version__ = "0.7.16"
APP_NAME = "WGSecure" APP_NAME = "WGSecure"
APP_SHORT = "WGS" APP_SHORT = "WGS"
+45 -14
View File
@@ -226,12 +226,12 @@ def _handle_connection(handle, logger: logging.Logger) -> None:
except ValidationError as e: except ValidationError as e:
resp = {"ok": False, "message": str(e)} resp = {"ok": False, "message": str(e)}
logger.info("%s -> ok=%s", cmd, resp.get("ok")) logger.info("%s -> ok=%s", cmd, resp.get("ok"))
except (pywintypes.error, ValueError, OSError) as e: except Exception as e:
logger.exception("Requête invalide ou erreur pipe") logger.exception("Requête invalide ou erreur pipe")
resp = {"ok": False, "message": f"Erreur interne : {e}"} resp = {"ok": False, "message": f"Erreur interne : {e}"}
try: try:
win32file.WriteFile(handle, (json.dumps(resp) + "\n").encode("utf-8")) win32file.WriteFile(handle, (json.dumps(resp) + "\n").encode("utf-8"))
except pywintypes.error: except Exception:
pass pass
@@ -273,26 +273,57 @@ class WGSecureHelperService(win32serviceutil.ServiceFramework):
) )
logger = _get_logger() logger = _get_logger()
logger.info("Service démarré") logger.info("Service démarré")
try:
self._serve_forever(logger)
except Exception:
# Filet de sécurité final : si malgré tout ce qui suit une
# exception s'échappe encore, elle laisse au moins une trace
# exploitable ici plutôt qu'un service qui disparaît en
# silence sans rien dans le log.
logger.exception("Arrêt inattendu de la boucle principale")
finally:
logger.info("Service arrêté")
def _serve_forever(self, logger: logging.Logger) -> None:
# Chaque étape est individuellement protégée et ne peut donc jamais
# faire sortir la boucle sur une exception non prévue : un service
# censé tourner indéfiniment sans surveillance ne doit jamais
# s'arrêter à cause d'un incident sur UNE requête. Une version
# antérieure ne capturait que pywintypes.error (pas Exception en
# général) et ne protégeait pas CloseHandle individuellement dans
# le `finally` : une erreur non prévue là pouvait remonter et
# arrêter tout le service — expliquant un premier échange réussi
# (juste après le démarrage du service) puis silence total ensuite.
ERROR_PIPE_CONNECTED = 535
while self._running: while self._running:
handle = None
try: try:
handle = _create_pipe_instance() handle = _create_pipe_instance()
except pywintypes.error: try:
logger.exception("Création du pipe impossible") win32pipe.ConnectNamedPipe(handle, None)
break except pywintypes.error as e:
try: # Le client s'est connecté entre CreateNamedPipe et
win32pipe.ConnectNamedPipe(handle, None) # ConnectNamedPipe : cas normal (pas une erreur), pas
# rare vu la fréquence des appels — sans ce cas
# particulier, la requête était silencieusement ratée
# à chaque fois qu'il se produisait.
if e.winerror != ERROR_PIPE_CONNECTED:
raise
if not self._running: if not self._running:
break break
_handle_connection(handle, logger) _handle_connection(handle, logger)
except pywintypes.error: except Exception:
logger.exception("Erreur sur une connexion cliente") logger.exception("Erreur sur une connexion cliente")
finally: finally:
try: if handle:
win32pipe.DisconnectNamedPipe(handle) try:
except pywintypes.error: win32pipe.DisconnectNamedPipe(handle)
pass except Exception:
win32file.CloseHandle(handle) pass
logger.info("Service arrêté") try:
win32file.CloseHandle(handle)
except Exception:
pass
if __name__ == "__main__": if __name__ == "__main__":
+1 -1
View File
@@ -5,7 +5,7 @@
; ────────────────────────────────────────────── ; ──────────────────────────────────────────────
#define MyAppName "WGSecure" #define MyAppName "WGSecure"
#define MyAppVersion "0.7.15" #define MyAppVersion "0.7.16"
#define MyAppPublisher "WGSecure" #define MyAppPublisher "WGSecure"
#define MyAppExeName "wgsecure.exe" #define MyAppExeName "wgsecure.exe"