diff --git a/modules/desktop-oo7-daemon.nix b/modules/desktop-oo7-daemon.nix index 90d42a9..67c6b73 100644 --- a/modules/desktop-oo7-daemon.nix +++ b/modules/desktop-oo7-daemon.nix @@ -22,11 +22,25 @@ # fresh `systemd-run --user` scope). { pkgs, ... }: +let + # 0.6.0 stops at LockedKeyring::open(login) when no keyring file exists, + # so on first run the auto-created default collection is locked and a + # client's Unlock() call routes to a prompt that never resolves (no + # gnome-shell / kwallet / gcr-prompter on a niri desktop). Cherry-pick + # upstream cf7b9a9 (PR #443) which uses the systemd credential / PAM + # secret to unlock the new keyring directly. Drop the override when + # nixpkgs ships an oo7-server release that includes the fix. + oo7-server = pkgs.oo7-server.overrideAttrs (old: { + patches = (old.patches or [ ]) ++ [ + ../patches/oo7-server/0001-server-Use-provided-secret-to-unlock-auto-created-de.patch + ]; + }); +in { - environment.systemPackages = [ pkgs.oo7-server ]; + environment.systemPackages = [ oo7-server ]; - services.dbus.packages = [ pkgs.oo7-server ]; - systemd.packages = [ pkgs.oo7-server ]; + services.dbus.packages = [ oo7-server ]; + systemd.packages = [ oo7-server ]; systemd.user.services.oo7-daemon = { wantedBy = [ "default.target" ]; diff --git a/patches/oo7-server/0001-server-Use-provided-secret-to-unlock-auto-created-de.patch b/patches/oo7-server/0001-server-Use-provided-secret-to-unlock-auto-created-de.patch new file mode 100644 index 0000000..a11e6b1 --- /dev/null +++ b/patches/oo7-server/0001-server-Use-provided-secret-to-unlock-auto-created-de.patch @@ -0,0 +1,115 @@ +From cf7b9a9fc53023cbaca5a128ece32d76cafe95d5 Mon Sep 17 00:00:00 2001 +From: Oscar Cowdery Lack +Date: Mon, 30 Mar 2026 00:05:49 +1100 +Subject: [PATCH] server: Use provided secret to unlock auto-created default + keyring (#443) + +If a secret is provided by PAM or systemd credentials, then it should be +used to unlock the default keyring when creating it for the first time, +not just when discovering existing keyrings. +--- + src/service/mod.rs | 36 +++++++++++++++++++++++++----------- + src/tests.rs | 4 +++- + 2 files changed, 28 insertions(+), 12 deletions(-) + +diff --git a/src/service/mod.rs b/src/service/mod.rs +index bfbe16d..44e55c2 100644 +--- a/src/service/mod.rs ++++ b/src/service/mod.rs +@@ -415,10 +415,10 @@ impl Service { + .await?; + + // Discover existing keyrings +- let discovered_keyrings = service.discover_keyrings(secret).await?; ++ let discovered_keyrings = service.discover_keyrings(secret.clone()).await?; + + service +- .initialize(connection, discovered_keyrings, true) ++ .initialize(connection, discovered_keyrings, secret, true) + .await?; + + // Start PAM listener +@@ -458,7 +458,7 @@ impl Service { + ) + .await?; + +- let default_keyring = if let Some(secret) = secret { ++ let default_keyring = if let Some(secret) = secret.clone() { + vec![( + "Login".to_owned(), + oo7::dbus::Service::DEFAULT_COLLECTION.to_owned(), +@@ -469,7 +469,7 @@ impl Service { + }; + + service +- .initialize(connection, default_keyring, false) ++ .initialize(connection, default_keyring, secret, false) + .await?; + Ok(service) + } +@@ -686,6 +686,7 @@ impl Service { + &self, + connection: zbus::Connection, + mut discovered_keyrings: Vec<(String, String, Keyring)>, // (name, alias, keyring) ++ secret: Option, + auto_create_default: bool, + ) -> Result<(), Error> { + self.connection.set(connection.clone()).unwrap(); +@@ -701,19 +702,32 @@ impl Service { + if !has_default && auto_create_default { + tracing::info!("No default collection found, creating 'Login' keyring"); + +- let locked_keyring = LockedKeyring::open(Self::LOGIN_ALIAS) +- .await +- .inspect_err(|e| { +- tracing::error!("Failed to create default Login keyring: {}", e); +- })?; ++ let keyring = if let Some(secret) = secret { ++ UnlockedKeyring::open(Self::LOGIN_ALIAS, secret) ++ .await ++ .map(Keyring::Unlocked) ++ } else { ++ LockedKeyring::open(Self::LOGIN_ALIAS) ++ .await ++ .map(Keyring::Locked) ++ }; ++ ++ let keyring = keyring.inspect_err(|e| { ++ tracing::error!("Failed to create default Login keyring: {}", e); ++ })?; + ++ let is_locked = if keyring.is_locked() { ++ "locked" ++ } else { ++ "unlocked" ++ }; + discovered_keyrings.push(( + "Login".to_owned(), + oo7::dbus::Service::DEFAULT_COLLECTION.to_owned(), +- Keyring::Locked(locked_keyring), ++ keyring, + )); + +- tracing::info!("Created default 'Login' collection (locked)"); ++ tracing::info!("Created default 'Login' collection ({})", is_locked); + } + + // Set up discovered collections +diff --git a/src/tests.rs b/src/tests.rs +index 16aa0bb..07fb27c 100644 +--- a/src/tests.rs ++++ b/src/tests.rs +@@ -254,7 +254,9 @@ impl TestServiceSetup { + .await?; + + let discovered = service.discover_keyrings(secret.clone()).await?; +- service.initialize(server_conn, discovered, false).await?; ++ service ++ .initialize(server_conn, discovered, secret.clone(), false) ++ .await?; + + #[cfg(any(feature = "gnome_native_crypto", feature = "gnome_openssl_crypto"))] + let mock_prompter = { +-- +2.53.0 +