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:
@@ -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é
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 :  — Septembre 2026
|
Version :  — Septembre 2026
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
__version__ = "0.7.15"
|
__version__ = "0.7.16"
|
||||||
APP_NAME = "WGSecure"
|
APP_NAME = "WGSecure"
|
||||||
APP_SHORT = "WGS"
|
APP_SHORT = "WGS"
|
||||||
|
|||||||
@@ -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
@@ -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"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user