# # Erminig - Fonctions pour gérer les utilisateurs système. # Copyright (C) 2025 L0m1g # Sous licence DOUARN - Voir le fichier LICENCE pour les détails # # Ce fichier fait partie du projet Erminig. # Libre comme l’air, stable comme un menhir, et salé comme le beurre. # import os import pwd import sys import functools def check_root(): """Vérifie si on est root, sinon quitte.""" if os.geteuid() != 0: print("[SECURITY] Ce programme doit être exécuté en tant que root.") sys.exit(1) def check_user_exists(username): """Vérifie si l'utilisateur spécifié existe.""" try: pwd.getpwnam(username) return True except KeyError: print(f"[SECURITY] Utilisateur '{username}' introuvable.") return False def run_as_user(username): """Décorateur : Fork et drop privileges pour exécuter une fonction sous un autre utilisateur.""" def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): try: pid = os.fork() if pid > 0: # Parent : attendre le child, ne pas exit, juste return proprement _, status = os.waitpid(pid, 0) return ( status >> 8 ) # récupère le code retour du fils (comme exit code) # Child pw_record = pwd.getpwnam(username) user_uid = pw_record.pw_uid user_gid = pw_record.pw_gid os.setgid(user_gid) os.setuid(user_uid) os.environ["HOME"] = pw_record.pw_dir os.environ["LOGNAME"] = pw_record.pw_name os.environ["USER"] = pw_record.pw_name result = func(*args, **kwargs) os._exit(0 if result is None else int(bool(result))) except OSError as e: print(f"[SECURITY] Fork échoué : {e}") os._exit(1) return wrapper return decorator