Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Linux Kernel Keyring lost the saved password after reboot #137

Closed
Berrysoft opened this issue Jul 2, 2023 · 10 comments
Closed

Comments

@Berrysoft
Copy link

I'm using this crate in headless mode with kernel keyring. However, my cosumer and myself have found that the saved password will be lost after reboot the system. I haven't found any information or documentation about that. Is it by design? Could I do someting to preserve the password?

@brotskydotcom
Copy link
Collaborator

cc'ing @landhb since he is more familiar with the kernel keyring.

My understanding (and what's documented in the keyring keystore itself) is that credentials are placed in the user's persistent keyring, which has a default persistence of 3 days. This lifetime can be adjusted by administrators. They keystore docs point you at the appropriate man pages for the underlying behaviors.

@landhb
Copy link
Contributor

landhb commented Jul 8, 2023

@Berrysoft @brotskydotcom That's correct, the kernel keystore is completely in-memory and will clear on a reboot.

The "persistent" keyring is persistent across sessions/logins but will still be wiped on a reboot.

Similar to how you need to unlock the Gnome Keyring with a password when you log-in, you'll need to re-prompt your users for a password after a reboot.

I noticed you're using a systems service, there is a systemd-ask-password utility that can be used to prompt the user when your service starts. manpage.

@Berrysoft
Copy link
Author

Thanks @landhb ! I think I need some other ways to save the password then:)

@brotskydotcom
Copy link
Collaborator

brotskydotcom commented Jul 10, 2023

I am reopening this as a doc bug because it's the second time it's come up; I had totally forgotten about it, and it's not documented in the keystore docs. So I need to fix that. Thanks for the discussion.

@Berrysoft There is a headless credential keeper for Unix systems called pass that you might want to check out. Here is a good article that explains how to run it headless and securely; here is another article that also talks about how to use it with GUI apps such as a browser. I would certainly welcome the contribution of a pass-based keystore for this module. (I notice there is what claims to be a rust implementation of pass in the passrs crate.)

@brotskydotcom brotskydotcom reopened this Jul 10, 2023
@landhb
Copy link
Contributor

landhb commented Jul 10, 2023

To clarify. This issue is a limitation for all secure storage.

Backend Memory Eviction User Interaction
Gnome Keyring On Logout User must re-enter their account password to unlock the keyring after logging in again. Unlocking the keyring with a master/account password allows Gnome to retrieve the encrypted credentials from disk.
Kernel Keyring On Reboot User must re-enter the credential or the application must prompt the user for a master password (to decrypt the contents from disk) or obtain the credential from a secure storage medium such as a Yubikey/TPM.
Pass Typically every run User must re-enter the master password to decrypt the contents from disk. Or enter a password to decrypt their GPG key which is stored on disk, and then the GPG key will be used to decrypt the password file.

In general, to have your secret accessible in-memory across reboots, something needs to be able to decrypt/access it securely from the filesystem.

That passrs crate is also highly insecure and stores the keys on disk in plaintext just in reverse order. So I wouldn't recommend using that crate. I also think password managers in general operate at a higher level of abstraction than this crate (and therefore should not be implemented as backends for this crate). A pass application could use this crate to store the master password between invocations of the CLI tool for instance.

@Berrysoft
Copy link
Author

Well, I think I need a beckend that is headless and unlocks on login. Gnome keyring unlocks on login, but it's not headless, and not all users install it. I choose to save the password directly on disk. It is a bit unsafe, but it is convenient.

@brotskydotcom
Copy link
Collaborator

@landhb Do the persistent credentials in the kernel keyring persist on disk between reboots or not? In the case of secret-service and pass, the credentials are all persisted on disk and there is a single master password that must be provided to decrypt them. My impression from your comments above is that the kernel keyring doesn't do any on-disk persistence, so if one has stored multiple credentials in it they are all lost on reboot. That's quite a different discipline than the others. That's what I think - if true - needs to be mentioned in the docs.

@Berrysoft The master password for pass is the password for the master GPG key used with the store. Most pass users arrange for this to be prompted for at headless login.

@landhb
Copy link
Contributor

landhb commented Jul 11, 2023

@brotskydotcom It does not persist on reboot. I agree that it should be mentioned in the docs.

Any on-disk persistence or prompting would need to be handled by the application itself, or offloaded to another source, such as gpg-agent like pass does, or systemd in the case of systemd-ask-password.

@landhb
Copy link
Contributor

landhb commented Jul 11, 2023

For CLI tools, it's a bit easier since the application can simply prompt the user. For instance, in one of my projects, I attempt to load from the platform keyring, and if that fails I prompt to decrypt from disk and cache the credential into the platform keyring.

impl CryptoAgent {
    /// Uses the provided configuration to locate the Vault and generate an
    /// Identity. First the agent will attempt to access the Identity file
    /// from the system keyring, if that fails then prompt for a password to
    /// decrypt it from disk.
    pub fn from_cfg(cfg: &VaultConfig, init: bool) -> Result<Self, Box<dyn Error>> {
        // Define keyring entry
        let service = env!("CARGO_BIN_NAME");
        let username = whoami::username();
        let entry = Entry::new(service, &username)?;

        // When initializing the keyring must be cleared
        if init {
            _ = entry.delete_password();
        }

        // Attempt to load
        Self::from_keyring(&entry, cfg).or_else(|_| Self::from_disk(&entry, cfg))
    }
}    

@brotskydotcom
Copy link
Collaborator

Thanks much to @landhb for the documentation fix (PR #138)!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants