From 3359bea98d8b05d0e0da688fa3657383cd29242b Mon Sep 17 00:00:00 2001 From: Olivier <1+olivier@noreply.raspot.in> Date: Wed, 19 Aug 2026 10:06:27 +0200 Subject: [PATCH] =?UTF-8?q?T=C3=A9l=C3=A9verser=20les=20fichiers=20vers=20?= =?UTF-8?q?"modules"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/workstation-setup.nix | 72 ++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/modules/workstation-setup.nix b/modules/workstation-setup.nix index 6849633..ecdd8d8 100644 --- a/modules/workstation-setup.nix +++ b/modules/workstation-setup.nix @@ -10,7 +10,8 @@ let #!${pkgs.expect}/bin/expect -f # Les secrets arrivent uniquement par stdin depuis l'application. - # Ils ne sont jamais placés dans argv et le transcript enfant n'est pas affiché. + # Ils ne sont jamais placés dans argv. La sortie du processus passwd + # reste masquée : seuls des jetons techniques non sensibles sont renvoyés. log_user 0 exp_internal 0 set timeout 30 @@ -30,22 +31,28 @@ let spawn -noecho ${pkgs.coreutils}/bin/env LC_ALL=C LANG=C /run/wrappers/bin/passwd - # Étape 1 : passwd doit demander le mot de passe actuel. + # Étape 1 : authentification du mot de passe actuel. + # Selon la pile PAM, l'invite peut être "Current password:", + # "(current) UNIX password:" OU simplement "Password:". + # Il ne faut donc pas dépendre uniquement des mots Current/Old/UNIX. expect { - -re {(?i)(current|old|unix).*password.*:} { - send -- "$current\r" - } - -re {(?i)new.*password.*:} { - fail "CURRENT_PROMPT_MISSING" 22 - } - -re {(?i)(authentication failure|incorrect password|password unchanged)} { + -re {(?i)(authentication failure|incorrect password|password unchanged|authentication token manipulation error)} { fail "CURRENT_REJECTED" 23 } + # Si passwd passe directement au nouveau mot de passe, nous refusons : + # l'assistant doit toujours vérifier le mot de passe temporaire actuel. + -re {(?i)(new|retype|repeat|confirm)[^\r\n]*(password|passphrase)[^\r\n]*[:?]} { + fail "CURRENT_PROMPT_MISSING" 22 + } + # Invite PAM générique, notamment "Password:". + -re {(?i)(password|passphrase)[^\r\n]*[:?]} { + send -- "$current\r" + } eof { - fail "CURRENT_REJECTED" 24 + fail "EARLY_EOF_CURRENT" 24 } timeout { - fail "TIMEOUT_CURRENT" 124 + fail "TIMEOUT_CURRENT_PROMPT" 124 } } @@ -54,49 +61,54 @@ let # Étape 2 : le nouveau mot de passe n'est envoyé qu'après validation # du mot de passe actuel par passwd/PAM. expect { - -re {(?i)new.*password.*:} { - send -- "$newpass\r" - } - # Certains passwd redemandent immédiatement le mot de passe courant - # après une erreur. On s'arrête sans envoyer une seconde tentative. - -re {(?i)(current|old|unix).*password.*:} { - fail "CURRENT_REJECTED" 25 - } -re {(?i)(authentication failure|incorrect password|password unchanged)} { fail "CURRENT_REJECTED" 25 } + -re {(?i)new[^\r\n]*(password|passphrase)[^\r\n]*[:?]} { + send -- "$newpass\r" + } + # Une invite générique "Password:" à ce stade est ambiguë : elle peut + # être une nouvelle demande du mot de passe actuel. Par sécurité nous + # ne tentons jamais une seconde authentification automatiquement. + -re {(?i)(password|passphrase)[^\r\n]*[:?]} { + fail "CURRENT_REPROMPT" 25 + } eof { - fail "CURRENT_REJECTED" 26 + fail "EARLY_EOF_NEW" 26 } timeout { - fail "TIMEOUT_NEW" 124 + fail "TIMEOUT_NEW_PROMPT" 124 } } - # Étape 3 : confirmation. Un nouveau prompt "New password" à ce stade - # signifie que PAM/passwd a refusé la valeur proposée. + # Étape 3 : confirmation du nouveau mot de passe. expect { - -re {(?i)(retype|repeat|confirm).*password.*:} { + -re {(?i)(bad password|password unchanged|authentication token manipulation error)} { + fail "NEW_REJECTED" 27 + } + -re {(?i)(retype|repeat|confirm)[^\r\n]*(password|passphrase)[^\r\n]*[:?]} { send -- "$confirm\r" } - -re {(?i)new.*password.*:} { + -re {(?i)new[^\r\n]*(password|passphrase)[^\r\n]*[:?]} { fail "NEW_REJECTED" 27 } eof { - fail "NEW_REJECTED" 28 + fail "EARLY_EOF_CONFIRM" 28 } timeout { - fail "TIMEOUT_CONFIRM" 124 + fail "TIMEOUT_CONFIRM_PROMPT" 124 } } set newpass "" set confirm "" + # Étape 4 : passwd doit maintenant terminer. Toute nouvelle invite de + # mot de passe signifie que la modification n'a pas été acceptée. expect { eof {} - -re {(?i)new.*password.*:} { - fail "NEW_REJECTED" 29 + -re {(?i)(password|passphrase)[^\r\n]*[:?]} { + fail "UNEXPECTED_PASSWORD_REPROMPT" 29 } timeout { fail "TIMEOUT_FINISH" 124 @@ -232,7 +244,7 @@ let workstationSetup = pkgs.stdenv.mkDerivation { pname = "nixos-workstations-setup"; - version = "1.3.0"; + version = "1.4.0"; src = ../workstation-setup;