diff --git a/app/sovran_systemsos_web/server.py b/app/sovran_systemsos_web/server.py index 8b29792..7e2a912 100644 --- a/app/sovran_systemsos_web/server.py +++ b/app/sovran_systemsos_web/server.py @@ -2060,6 +2060,29 @@ async def api_migration_password_acknowledge(): except Exception as exc: logger.warning("chpasswd exception during migration acknowledge: %s", exc) + # Wipe the old keyring (encrypted with the pre-migration password) and + # seed the default pointer so PAM creates a fresh keyring on next login. + keyring_dir = "/home/free/.local/share/keyrings" + try: + if os.path.isdir(keyring_dir): + for entry in os.listdir(keyring_dir): + entry_path = os.path.join(keyring_dir, entry) + try: + if os.path.isfile(entry_path) or os.path.islink(entry_path): + os.unlink(entry_path) + elif os.path.isdir(entry_path): + shutil.rmtree(entry_path, ignore_errors=True) + except Exception: + pass + os.makedirs(keyring_dir, exist_ok=True) + default_file = os.path.join(keyring_dir, "default") + with open(default_file, "w") as f: + f.write("login\n") + free_pw = pwd.getpwnam("free") + os.chown(default_file, free_pw.pw_uid, free_pw.pw_gid) + except Exception as exc: + logger.warning("Keyring wipe exception during migration acknowledge: %s", exc) + # Clear the pending marker try: os.remove(MIGRATION_NEWPASS_FILE) @@ -3907,6 +3930,18 @@ async def api_security_reset(): except Exception as exc: errors.append(f"keyring wipe: {exc}") + # Recreate the default pointer so pam_gnome_keyring knows which keyring to + # unlock on the next GDM login without prompting the user. + try: + os.makedirs(keyring_dir, exist_ok=True) + default_file = os.path.join(keyring_dir, "default") + with open(default_file, "w") as f: + f.write("login\n") + free_pw = pwd.getpwnam("free") + os.chown(default_file, free_pw.pw_uid, free_pw.pw_gid) + except Exception as exc: + errors.append(f"keyring default recreation: {exc}") + # The user performed a full security reset — the banner's purpose is served. try: os.makedirs(os.path.dirname(SECURITY_BANNER_DISMISSED_FLAG), exist_ok=True) diff --git a/modules/credentials.nix b/modules/credentials.nix index dfc5d89..e1e33e6 100644 --- a/modules/credentials.nix +++ b/modules/credentials.nix @@ -35,6 +35,8 @@ let echo "Password for 'free' updated and saved." # Delete the old GNOME Keyring so it is recreated with the new password on next GDM login. rm -rf /home/free/.local/share/keyrings/* + # Recreate the default pointer so PAM knows which keyring to unlock. + su - free -c 'echo "login" > ~/.local/share/keyrings/default' echo "GNOME Keyring files cleared — a fresh keyring will be created on next login." ''; in @@ -182,6 +184,15 @@ in echo "$FREE_PASS" > "$SECRET_FILE" chmod 600 "$SECRET_FILE" echo "free:$FREE_PASS" | chpasswd + # Seed the GNOME Keyring default pointer so PAM creates a fresh keyring + # on first login without prompting the user. Guard with -f so we never + # overwrite an existing pointer on legacy machines that already have one. + su - free -c ' + mkdir -p ~/.local/share/keyrings + if [ ! -f ~/.local/share/keyrings/default ]; then + echo "login" > ~/.local/share/keyrings/default + fi + ' ''; };