Home-Verschlüsselung: Fixes aus dem grafischen Test auf VM 107

- Bildschirmsperre: Hook läuft dort als Benutzer und ließ das Entsperren
  scheitern; ohne root beendet er sich jetzt ohne Fehler.
- Wiederherstellung: ein schon entsperrtes Home ließ jeden Schlüssel durch;
  der Hook sperrt jetzt vor der Prüfung.
- Anmeldebildschirm: kurze Meldungszeilen (slick-greeter schneidet ab);
  passwort-hinweis zeigt während der Wiederherstellung keinen QR-Code und
  startet den Anmeldebildschirm nicht neu, sonst wäre die Meldung weg.
- Dialog: "Später" passt jetzt zum Text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-28 07:14:59 +01:00
1 parent b26dfd4f96
commit bda13b5b6f
3 files changed
+65 -18

No files matched your search

@@ -61,6 +61,11 @@ schluessel_normalisieren() {
}
pam_vorbereiten() {
# Bildschirmsperre (cinnamon-screensaver) prüft als der Benutzer selbst:
# dann läuft schon eine Sitzung mit entsperrtem Home, und ohne root
# ginge hier ohnehin nichts. Ein Fehler hier ließe das Entsperren
# scheitern (VM 107, 28.10.2026).
[ "$(id -u)" -eq 0 ] || exit 0
benutzer="${PAM_USER:-}"
[ -n "${benutzer}" ] || exit 0
# fscrypt prüft Passwörter selbst über PAM (Dienst "fscrypt") und riefe
@@ -90,8 +95,10 @@ erstanmeldung() {
( umask 077 && printf '%s' "${authtok}" > "${MERKEN_DIR}/${benutzer}" )
unset authtok
log "${benutzer}: Passwort zurückgesetzt, warte auf Wiederherstellungsschlüssel"
meldung "Dein Passwort wurde zurückgesetzt. Dein Home-Ordner ist verschlüsselt und braucht einmal deinen Wiederherstellungsschlüssel."
meldung "Gib jetzt den Wiederherstellungsschlüssel (Form XXXX-XXXX-XXXX-XXXX-XXXX-XXXX) in das Passwortfeld ein."
# Kurze Zeilen: slick-greeter schneidet längere ab.
meldung "Passwort zurückgesetzt."
meldung "Jetzt den Wiederherstellungsschlüssel"
meldung "ins Passwortfeld eingeben."
exit 1
fi
@@ -104,7 +111,8 @@ erstanmeldung() {
fi
if [ -e "${home}" ] && [ -n "$(ls -A "${home}" 2>/dev/null)" ]; then
log "${benutzer}: ${home} ist nicht leer, verschlüssele nicht"
meldung "Dein Home-Ordner kann nicht verschlüsselt werden. Bitte wende dich an die Verwaltung."
meldung "Home-Ordner nicht einrichtbar."
meldung "Bitte an die Verwaltung wenden."
exit 1
fi
@@ -118,7 +126,8 @@ erstanmeldung() {
if ! ausgabe="$(printf '%s' "${authtok}" | fscrypt encrypt "${home}" --source=pam_passphrase --user="${benutzer}" --no-recovery --quiet 2>&1)"; then
log "${benutzer}: fscrypt encrypt fehlgeschlagen: ${ausgabe}"
rmdir "${home}" 2>/dev/null
meldung "Dein Home-Ordner konnte nicht verschlüsselt werden. Bitte wende dich an die Verwaltung."
meldung "Home-Ordner nicht einrichtbar."
meldung "Bitte an die Verwaltung wenden."
exit 1
fi
@@ -131,7 +140,8 @@ erstanmeldung() {
! wh="$(wh_protektor "${benutzer}")" || [ -z "${wh}" ] ||
! ausgabe="$(printf '%s\n%s\n' "${schluessel}" "${authtok}" | fscrypt metadata add-protector-to-policy --protector="/:${wh}" --policy="/:${policy}" --unlock-with="/:${login}" --quiet 2>&1)"; then
log "${benutzer}: Wiederherstellungsschlüssel nicht angelegt: ${ausgabe}"
meldung "Dein Home-Ordner konnte nicht eingerichtet werden. Bitte wende dich an die Verwaltung."
meldung "Home-Ordner nicht einrichtbar."
meldung "Bitte an die Verwaltung wenden."
exit 1
fi
unset authtok
@@ -178,20 +188,30 @@ schluessel() {
policy="$(policy_von "${home}")"
if [ -z "${wh}" ] || [ -z "${policy}" ]; then
log "${benutzer}: Wiederherstellung nicht möglich (Protektor ${wh:-fehlt}, Policy ${policy:-fehlt})"
meldung "Dein Home-Ordner lässt sich nicht wiederherstellen. Bitte wende dich an die Verwaltung."
meldung "Wiederherstellung nicht möglich."
meldung "Bitte an die Verwaltung wenden."
exit 1
fi
# Erst den Schlüssel prüfen, dann den alten Login-Protektor entfernen.
if ! ausgabe="$(printf '%s\n' "${eingabe}" | fscrypt unlock "${home}" --unlock-with="/:${wh}" --user="${benutzer}" --quiet 2>&1)"; then
case "${ausgabe}" in
*"already unlocked"*) ;;
*)
log "${benutzer}: Wiederherstellungsschlüssel abgelehnt"
meldung "Der Wiederherstellungsschlüssel stimmt nicht. Versuche es noch einmal."
exit 1
;;
esac
# Geprüft wird durch Entsperren; ein schon entsperrtes Home (Sitzung
# oder frühere Wiederherstellung) ließe sonst jeden Schlüssel durch
# (VM 107, 28.10.2026). Also vorher sperren; geht das nicht, läuft noch
# eine Sitzung des Benutzers.
if fscrypt status "${home}" 2>/dev/null | grep -q '^Unlocked: Yes'; then
fscrypt lock "${home}" --user="${benutzer}" --quiet >/dev/null 2>&1
if fscrypt status "${home}" 2>/dev/null | grep -q '^Unlocked: Yes'; then
log "${benutzer}: Home noch entsperrt (Sitzung?), Wiederherstellung abgebrochen"
meldung "Bitte erst überall abmelden"
meldung "oder das Gerät neu starten."
exit 1
fi
fi
if ! printf '%s\n' "${eingabe}" | fscrypt unlock "${home}" --unlock-with="/:${wh}" --user="${benutzer}" --quiet >/dev/null 2>&1; then
log "${benutzer}: Wiederherstellungsschlüssel abgelehnt"
meldung "Schlüssel stimmt nicht."
meldung "Bitte noch einmal eingeben."
exit 1
fi
# Pro Benutzer gibt es nur einen Login-Protektor je Dateisystem: den
@@ -207,12 +227,18 @@ schluessel() {
! ausgabe="$(printf '%s\n%s\n' "${passwort}" "${eingabe}" | fscrypt metadata add-protector-to-policy --protector="/:${login}" --policy="/:${policy}" --unlock-with="/:${wh}" --quiet 2>&1)"; then
unset passwort eingabe
log "${benutzer}: neuer Login-Protektor fehlgeschlagen: ${ausgabe}"
meldung "Die Wiederherstellung ist fehlgeschlagen. Melde dich noch einmal mit deinem Passwort an und gib danach den Schlüssel erneut ein."
meldung "Wiederherstellung fehlgeschlagen."
meldung "Neu beginnen: erst das neue Passwort."
rm -f "${gemerkt}"
exit 1
fi
unset passwort eingabe
rm -f "${gemerkt}" "${m}.wiederherstellung"
# Für passwort-hinweis.py (Rolle personalisierung): der Schlüssel im
# Passwortfeld ist für pam_unix eine Fehleingabe; ohne diese Marke zeigte
# der Dienst den QR-Code und startete den Anmeldebildschirm neu, und die
# Meldung unten wäre weg.
touch "${MERKEN_DIR}/${benutzer}.erledigt"
# Der Schlüsselbund ist noch mit dem alten Passwort verschlüsselt (wie
# schluesselbund_wegsichern in persoenliche-konten.py, das beim Reset
@@ -223,7 +249,8 @@ schluessel() {
fi
log "${benutzer}: Home mit Wiederherstellungsschlüssel auf neues Passwort umgestellt"
meldung "Dein Home-Ordner ist wiederhergestellt. Melde dich jetzt mit deinem Passwort an."
meldung "Home-Ordner wiederhergestellt."
meldung "Jetzt mit dem neuen Passwort anmelden."
exit 1
}
@@ -58,7 +58,7 @@ Gerät <b>${geraet}</b>, Anmeldename <b>${USER}</b>
Drucke ihn aus, speichere ihn als PDF außerhalb dieses Geräts oder schreibe
ihn ab. Bewahre ihn sicher und getrennt vom Gerät auf.
Er wird nur dieses eine Mal angezeigt."
Nach der Bestätigung wird er nicht mehr angezeigt."
while true; do
antwort="$(zenity --question --title="Wiederherstellungsschlüssel" --width=520 --no-wrap \
@@ -34,6 +34,13 @@ STAND_DIR = "/var/lib/tuxflotte/passwort-hinweis"
STAND_PATH = os.path.join(STAND_DIR, "stand.json")
GAST_ANGEBOT = "/run/tuxflotte/passwort-hinweis-gast.json"
KONTEN_DIR = "/var/lib/tuxflotte/persoenliche-konten"
# Verschlüsseltes Home nach einem Reset (Rolle persoenliche-konten,
# home-verschluesselung): Der Wiederherstellungsschlüssel kommt ins
# Passwortfeld und ist für pam_unix eine Fehleingabe. Dann kein QR-Code und
# kein Neustart des Anmeldebildschirms, sonst wären die Hinweise des Hooks
# weg (VM 107, 28.10.2026).
WIEDERHERSTELLUNG_DIR = "/run/tuxflotte-home"
WIEDERHERSTELLUNG_NACHLAUF_SEKUNDEN = 300
GAST = "gast"
SICHTBAR_SEKUNDEN = 15 * 60
# Nach einer Gastanmeldung bleibt das Angebot nur so lange liegen, bis die
@@ -96,6 +103,16 @@ def entscheiden(zeile, konten, stand, jetzt):
return None
def wiederherstellung_laeuft(name, jetzt):
if os.path.exists(os.path.join(KONTEN_DIR, f"{name}.wiederherstellung")):
return True
try:
erledigt = os.path.getmtime(os.path.join(WIEDERHERSTELLUNG_DIR, f"{name}.erledigt"))
except OSError:
return False
return jetzt - erledigt < WIEDERHERSTELLUNG_NACHLAUF_SEKUNDEN
def seiten_url(einstellungen, name):
abfrage = urllib.parse.urlencode({"geraet": einstellungen["geraet"], "t": einstellungen["token"], "konto": name})
return f"{einstellungen['url']}?{abfrage}"
@@ -354,6 +371,9 @@ def main():
log("journalctl beendet")
sys.exit(1)
aktion = entscheiden(zeile, persoenliche_konten(), stand.get("bis", {}), jetzt)
if aktion and aktion[0] in ("zeigen", "verlaengern") and wiederherstellung_laeuft(aktion[1], jetzt):
log(f"Fehleingabe für {aktion[1]} während der Wiederherstellung: kein Hinweis")
aktion = None
if aktion and aktion[0] == "zeigen":
zeigen(aktion[1], einstellungen, stand, jetzt)
elif aktion and aktion[0] == "verlaengern" and not hinweis_sichtbar(aktion[1]):