From 51338689511e5a78f8adb9753afd43b59efce19a Mon Sep 17 00:00:00 2001 From: Johnny Date: Fri, 4 Sep 2026 21:26:32 +0200 Subject: [PATCH] chore(release): v0.7.15 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrige helper_ipc.py : seul CreateFileW avait des argtypes/restype ctypes explicites. Sans eux pour ReadFile/WriteFile/CloseHandle, le HANDLE (pointeur 64 bits) était marshalé comme un entier 32 bits par défaut et tronqué silencieusement, faisant échouer systématiquement l'échange avec wgsecure-helper — l'app retombait donc toujours sur son chemin élevé (2 invites UAC) malgré un service qui tournait et répondait correctement. Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 7 ++++ Makefile | 2 +- README.md | 4 +- app/__init__.py | 2 +- app/utils/helper_ipc.py | 87 +++++++++++++++++++++++++++-------------- wgsecure.iss | 2 +- 6 files changed, 70 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8422a48..a785fa8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ Ce projet suit le [Versionnage Sémantique](https://semver.org/lang/fr/). --- +## [0.7.15] — 2026-09-04 + +### Corrigé +- **Le service `wgsecure-helper` n'était jamais réellement utilisé par l'app** (split-DNS fonctionnait, mais toujours via le chemin élevé — 2 invites UAC à la connexion au lieu de 0). Le client du pipe (`app/utils/helper_ipc.py`) ne déclarait les signatures `ctypes` explicites que pour `CreateFileW` : sans elles, `ReadFile`/`WriteFile`/`CloseHandle` marshalaient le HANDLE (pointeur 64 bits) comme un entier 32 bits par défaut, le tronquant silencieusement — l'échange avec le service échouait alors systématiquement, et l'app retombait sur son ancien chemin élevé sans que rien ne le signale. Signatures explicites ajoutées pour chaque appel. + +--- + ## [0.7.14] — 2026-09-04 ### Corrigé diff --git a/Makefile b/Makefile index c608e54..d71fdf8 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ ## ────────────────────────────────────────────── APP := wgsecure -VERSION := 0.7.14 +VERSION := 0.7.15 VENV := .venv PYTHON := $(VENV)/bin/python3 PIP := $(VENV)/bin/pip diff --git a/README.md b/README.md index ca2b498..2a2317d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🛡️ WGSecure (WGS) -🚀 v0.7.14 · 🐍 · 🪟🐧 · 🔐 MFA TOTP · 🛡️ WireGuard +🚀 v0.7.15 · 🐍 · 🪟🐧 · 🔐 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). @@ -210,4 +210,4 @@ WGSecure/ ## 👤 Auteur Développé par **Johnny** — [JT-Tools](https://github.com/JT-Tools) -Version : ![v0.7.14](https://img.shields.io/badge/v0.7.14-septembre%202026-2980b9?style=flat-square) — Septembre 2026 +Version : ![v0.7.15](https://img.shields.io/badge/v0.7.15-septembre%202026-2980b9?style=flat-square) — Septembre 2026 diff --git a/app/__init__.py b/app/__init__.py index b05d1c5..acff5e0 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,3 +1,3 @@ -__version__ = "0.7.14" +__version__ = "0.7.15" APP_NAME = "WGSecure" APP_SHORT = "WGS" diff --git a/app/utils/helper_ipc.py b/app/utils/helper_ipc.py index 357e50d..d450e65 100644 --- a/app/utils/helper_ipc.py +++ b/app/utils/helper_ipc.py @@ -34,37 +34,59 @@ def call_helper(request: dict, timeout_ms: int = 1500) -> dict | None: import ctypes from ctypes import wintypes - GENERIC_READ = 0x80000000 - GENERIC_WRITE = 0x40000000 - OPEN_EXISTING = 3 - FILE_ATTRIBUTE_NORMAL = 0x80 - INVALID_HANDLE_VALUE = ctypes.c_void_p(-1).value - - kernel32 = ctypes.windll.kernel32 - kernel32.CreateFileW.restype = wintypes.HANDLE - kernel32.CreateFileW.argtypes = [ - wintypes.LPCWSTR, wintypes.DWORD, wintypes.DWORD, - wintypes.LPVOID, wintypes.DWORD, wintypes.DWORD, wintypes.HANDLE, - ] - - # Un pipe dont toutes les instances sont déjà occupées fait échouer - # CreateFile immédiatement (ERROR_PIPE_BUSY) : WaitNamedPipe patiente - # qu'une instance se libère, dans la limite du timeout. Sans effet (et - # sans erreur bloquante) si le pipe n'existe pas du tout — CreateFile - # échouera juste ensuite avec ERROR_FILE_NOT_FOUND. + handle = None + kernel32 = None try: + GENERIC_READ = 0x80000000 + GENERIC_WRITE = 0x40000000 + OPEN_EXISTING = 3 + FILE_ATTRIBUTE_NORMAL = 0x80 + INVALID_HANDLE_VALUE = ctypes.c_void_p(-1).value + + kernel32 = ctypes.windll.kernel32 + # Signatures explicites pour CHAQUE fonction utilisée : sans + # argtypes, ctypes marshalle un HANDLE (pointeur 64 bits) comme un + # c_int par défaut sur Windows 64 bits, le tronquant silencieusement + # — ReadFile/WriteFile/CloseHandle échouaient alors sur un handle + # corrompu, cet échec étant avalé par le retour `None` (best- + # effort), ce qui faisait retomber *systématiquement* sur le chemin + # élevé (UAC) sans que rien ne signale que le pipe avait pourtant + # été ouvert avec succès. + kernel32.CreateFileW.restype = wintypes.HANDLE + kernel32.CreateFileW.argtypes = [ + wintypes.LPCWSTR, wintypes.DWORD, wintypes.DWORD, + wintypes.LPVOID, wintypes.DWORD, wintypes.DWORD, wintypes.HANDLE, + ] + kernel32.WaitNamedPipeW.restype = wintypes.BOOL + kernel32.WaitNamedPipeW.argtypes = [wintypes.LPCWSTR, wintypes.DWORD] + kernel32.ReadFile.restype = wintypes.BOOL + kernel32.ReadFile.argtypes = [ + wintypes.HANDLE, wintypes.LPVOID, wintypes.DWORD, + ctypes.POINTER(wintypes.DWORD), wintypes.LPVOID, + ] + kernel32.WriteFile.restype = wintypes.BOOL + kernel32.WriteFile.argtypes = [ + wintypes.HANDLE, wintypes.LPCVOID, wintypes.DWORD, + ctypes.POINTER(wintypes.DWORD), wintypes.LPVOID, + ] + kernel32.CloseHandle.restype = wintypes.BOOL + kernel32.CloseHandle.argtypes = [wintypes.HANDLE] + + # Un pipe dont toutes les instances sont déjà occupées fait échouer + # CreateFile immédiatement (ERROR_PIPE_BUSY) : WaitNamedPipe patiente + # qu'une instance se libère, dans la limite du timeout. Sans effet + # (et sans erreur bloquante) si le pipe n'existe pas du tout — + # CreateFile échouera juste ensuite avec ERROR_FILE_NOT_FOUND. kernel32.WaitNamedPipeW(_PIPE_NAME, timeout_ms) - except OSError: - pass - handle = kernel32.CreateFileW( - _PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, None, - ) - if not handle or handle == INVALID_HANDLE_VALUE: - return None + handle = kernel32.CreateFileW( + _PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, None, + ) + if not handle or handle == INVALID_HANDLE_VALUE: + handle = None + return None - try: payload = (json.dumps(request) + "\n").encode("utf-8") written = wintypes.DWORD(0) ok = kernel32.WriteFile(handle, payload, len(payload), @@ -89,7 +111,14 @@ def call_helper(request: dict, timeout_ms: int = 1500) -> dict | None: line = data.split(b"\n", 1)[0] resp = json.loads(line.decode("utf-8")) return resp if isinstance(resp, dict) else None - except (OSError, ValueError): + except Exception: + # Best-effort pur : n'importe quel pépin (pipe absent, ctypes, + # décodage…) doit basculer l'appelant sur son chemin existant, + # jamais lever jusqu'à lui. return None finally: - kernel32.CloseHandle(handle) + if handle and kernel32: + try: + kernel32.CloseHandle(handle) + except Exception: + pass diff --git a/wgsecure.iss b/wgsecure.iss index b09f49a..595b1f9 100644 --- a/wgsecure.iss +++ b/wgsecure.iss @@ -5,7 +5,7 @@ ; ────────────────────────────────────────────── #define MyAppName "WGSecure" -#define MyAppVersion "0.7.14" +#define MyAppVersion "0.7.15" #define MyAppPublisher "WGSecure" #define MyAppExeName "wgsecure.exe"