chore(release): v0.7.15
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 <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.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
|
## [0.7.14] — 2026-09-04
|
||||||
|
|
||||||
### Corrigé
|
### Corrigé
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
## ──────────────────────────────────────────────
|
## ──────────────────────────────────────────────
|
||||||
|
|
||||||
APP := wgsecure
|
APP := wgsecure
|
||||||
VERSION := 0.7.14
|
VERSION := 0.7.15
|
||||||
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.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).
|
**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.14"
|
__version__ = "0.7.15"
|
||||||
APP_NAME = "WGSecure"
|
APP_NAME = "WGSecure"
|
||||||
APP_SHORT = "WGS"
|
APP_SHORT = "WGS"
|
||||||
|
|||||||
+58
-29
@@ -34,37 +34,59 @@ def call_helper(request: dict, timeout_ms: int = 1500) -> dict | None:
|
|||||||
import ctypes
|
import ctypes
|
||||||
from ctypes import wintypes
|
from ctypes import wintypes
|
||||||
|
|
||||||
GENERIC_READ = 0x80000000
|
handle = None
|
||||||
GENERIC_WRITE = 0x40000000
|
kernel32 = None
|
||||||
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.
|
|
||||||
try:
|
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)
|
kernel32.WaitNamedPipeW(_PIPE_NAME, timeout_ms)
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
handle = kernel32.CreateFileW(
|
handle = kernel32.CreateFileW(
|
||||||
_PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None,
|
_PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None,
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, None,
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, None,
|
||||||
)
|
)
|
||||||
if not handle or handle == INVALID_HANDLE_VALUE:
|
if not handle or handle == INVALID_HANDLE_VALUE:
|
||||||
return None
|
handle = None
|
||||||
|
return None
|
||||||
|
|
||||||
try:
|
|
||||||
payload = (json.dumps(request) + "\n").encode("utf-8")
|
payload = (json.dumps(request) + "\n").encode("utf-8")
|
||||||
written = wintypes.DWORD(0)
|
written = wintypes.DWORD(0)
|
||||||
ok = kernel32.WriteFile(handle, payload, len(payload),
|
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]
|
line = data.split(b"\n", 1)[0]
|
||||||
resp = json.loads(line.decode("utf-8"))
|
resp = json.loads(line.decode("utf-8"))
|
||||||
return resp if isinstance(resp, dict) else None
|
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
|
return None
|
||||||
finally:
|
finally:
|
||||||
kernel32.CloseHandle(handle)
|
if handle and kernel32:
|
||||||
|
try:
|
||||||
|
kernel32.CloseHandle(handle)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
; ──────────────────────────────────────────────
|
; ──────────────────────────────────────────────
|
||||||
|
|
||||||
#define MyAppName "WGSecure"
|
#define MyAppName "WGSecure"
|
||||||
#define MyAppVersion "0.7.14"
|
#define MyAppVersion "0.7.15"
|
||||||
#define MyAppPublisher "WGSecure"
|
#define MyAppPublisher "WGSecure"
|
||||||
#define MyAppExeName "wgsecure.exe"
|
#define MyAppExeName "wgsecure.exe"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user