124 lines
3.7 KiB
Python
124 lines
3.7 KiB
Python
import sys
|
|
import os
|
|
import subprocess
|
|
import platform
|
|
|
|
|
|
def is_windows() -> bool:
|
|
return sys.platform == "win32"
|
|
|
|
|
|
def is_linux() -> bool:
|
|
return sys.platform.startswith("linux")
|
|
|
|
|
|
def get_config_dir() -> str:
|
|
if is_windows():
|
|
base = os.environ.get("APPDATA", os.path.expanduser("~"))
|
|
path = os.path.join(base, "WGSecure")
|
|
else:
|
|
path = os.path.join(os.path.expanduser("~"), ".wgsecure")
|
|
os.makedirs(path, exist_ok=True)
|
|
return path
|
|
|
|
|
|
def get_wg_config_dir() -> str:
|
|
if is_windows():
|
|
base = os.environ.get("PROGRAMDATA", r"C:\ProgramData")
|
|
return os.path.join(base, "WireGuard")
|
|
return "/etc/wireguard"
|
|
|
|
|
|
def has_root_privileges() -> bool:
|
|
if is_windows():
|
|
try:
|
|
import ctypes
|
|
return ctypes.windll.shell32.IsUserAnAdmin() != 0
|
|
except Exception:
|
|
return False
|
|
return os.geteuid() == 0
|
|
|
|
|
|
def run_command(cmd: list[str], timeout: int = 10) -> tuple[int, str, str]:
|
|
try:
|
|
result = subprocess.run(
|
|
cmd,
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=timeout,
|
|
)
|
|
return result.returncode, result.stdout.strip(), result.stderr.strip()
|
|
except subprocess.TimeoutExpired:
|
|
return -1, "", "Timeout"
|
|
except FileNotFoundError:
|
|
return -1, "", f"Commande introuvable : {cmd[0]}"
|
|
except Exception as e:
|
|
return -1, "", str(e)
|
|
|
|
|
|
def run_privileged(cmd: list[str], timeout: int = 10) -> tuple[int, str, str]:
|
|
if is_windows():
|
|
return run_command(cmd, timeout)
|
|
if has_root_privileges():
|
|
return run_command(cmd, timeout)
|
|
# Tente pkexec puis sudo
|
|
for elevator in ("pkexec", "sudo"):
|
|
code, out, err = run_command([elevator] + cmd, timeout)
|
|
if code != -1 or "introuvable" not in err:
|
|
return code, out, err
|
|
return -1, "", "Élévation de privilèges impossible"
|
|
|
|
|
|
def wg_available() -> bool:
|
|
code, _, _ = run_command(["wg", "--version"])
|
|
return code == 0
|
|
|
|
|
|
def wg_quick_available() -> bool:
|
|
if is_windows():
|
|
code, _, _ = run_command(["wireguard", "--help"])
|
|
return code == 0
|
|
code, _, _ = run_command(["wg-quick", "--help"])
|
|
return code == 0
|
|
|
|
|
|
def install_desktop_entry(icon_png_path: str) -> None:
|
|
"""Installe l'entrée .desktop et l'icône PNG pour la barre des tâches GNOME/KDE.
|
|
Appelé une fois au démarrage ; sans effet sur Windows."""
|
|
if is_windows():
|
|
return
|
|
try:
|
|
# Icône dans le thème hicolor
|
|
icon_dir = os.path.expanduser("~/.local/share/icons/hicolor/256x256/apps")
|
|
os.makedirs(icon_dir, exist_ok=True)
|
|
dest_icon = os.path.join(icon_dir, "wgsecure.png")
|
|
import shutil
|
|
shutil.copy2(icon_png_path, dest_icon)
|
|
|
|
# Fichier .desktop
|
|
app_dir = os.path.expanduser("~/.local/share/applications")
|
|
os.makedirs(app_dir, exist_ok=True)
|
|
script = os.path.abspath(
|
|
os.path.join(os.path.dirname(__file__), "..", "..", "main.py")
|
|
)
|
|
desktop = os.path.join(app_dir, "wgsecure.desktop")
|
|
content = (
|
|
"[Desktop Entry]\n"
|
|
"Type=Application\n"
|
|
"Name=WGSecure\n"
|
|
"Comment=WireGuard GUI avec MFA TOTP\n"
|
|
f"Exec=python3 {script}\n"
|
|
"Icon=wgsecure\n"
|
|
"Categories=Network;Security;\n"
|
|
"StartupWMClass=main\n"
|
|
"Terminal=false\n"
|
|
)
|
|
with open(desktop, "w") as f:
|
|
f.write(content)
|
|
|
|
# Mettre à jour le cache d'icônes si disponible
|
|
run_command(["gtk-update-icon-cache", "-f", "-t",
|
|
os.path.expanduser("~/.local/share/icons/hicolor")])
|
|
except Exception:
|
|
pass
|