mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 11:01:07 +00:00
155 lines
6.6 KiB
Diff
155 lines
6.6 KiB
Diff
--- a/crates/xodus/src/secrets.rs
|
|
+++ b/crates/xodus/src/secrets.rs
|
|
@@ -1,73 +1,14 @@
|
|
-pub static SERVICE_NAME: &str = "Xodus Service";
|
|
+use crate::tokens::{backend::KeychainBackend, store::{TokenBackend, TokenStoreError}};
|
|
|
|
pub fn init_secrets() -> Result<(), keyring_core::Error> {
|
|
- #[cfg(feature = "key-chain-file")]
|
|
- {
|
|
- let store = keyring_core::sample::Store::new_with_backing(
|
|
- secrets_backing_file()
|
|
- .to_str()
|
|
- .expect("Invalid secrets backing path"),
|
|
- )?;
|
|
- keyring_core::set_default_store(store);
|
|
- }
|
|
-
|
|
- #[cfg(not(feature = "key-chain-file"))]
|
|
- {
|
|
- #[cfg(target_os = "linux")]
|
|
- {
|
|
- activate_desktop_keyring();
|
|
- keyring_core::set_default_store(dbus_secret_service_keyring_store::Store::new()?);
|
|
- }
|
|
-
|
|
- #[cfg(target_os = "macos")]
|
|
- {
|
|
- keyring_core::set_default_store(apple_native_keyring_store::keychain::Store::new()?);
|
|
- }
|
|
-
|
|
- #[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
|
- {
|
|
- let store = keyring_core::sample::Store::new_with_configuration(
|
|
- &std::collections::HashMap::from([("persist", "true")]),
|
|
- )?;
|
|
- keyring_core::set_default_store(store);
|
|
- }
|
|
- }
|
|
-
|
|
+ if std::env::var_os("DROIDDECK_XBOX_CREDENTIAL_SOCKET").is_none() { return Err(keyring_core::Error::NoEntry); }
|
|
Ok(())
|
|
}
|
|
-
|
|
-// Some KDE installations advertise ksecretd only under its compatibility
|
|
-// activation name. Respect an existing/default Secret Service provider first.
|
|
-// This starts a packaged user service, never installs or configures a keyring.
|
|
-#[cfg(all(target_os = "linux", not(feature = "key-chain-file")))]
|
|
-fn activate_desktop_keyring() {
|
|
- use dbus::blocking::Connection;
|
|
- use std::time::Duration;
|
|
- let Ok(connection) = Connection::new_session() else { return; };
|
|
- let bus = connection.with_proxy("org.freedesktop.DBus", "/org/freedesktop/DBus", Duration::from_secs(3));
|
|
- let Ok((owned,)): Result<(bool,), _> = bus.method_call("org.freedesktop.DBus", "NameHasOwner", ("org.freedesktop.secrets",)) else { return; };
|
|
- if owned { return; }
|
|
- let Ok((names,)): Result<(Vec<String>,), _> = bus.method_call("org.freedesktop.DBus", "ListActivatableNames", ()) else { return; };
|
|
- if names.iter().any(|name| name == "org.freedesktop.secrets") { return; }
|
|
- if names.iter().any(|name| name == "org.kde.secretservicecompat") {
|
|
- // On failure, Store::new below still returns the genuine keyring error.
|
|
- let _: Result<(u32,), _> = bus.method_call("org.freedesktop.DBus", "StartServiceByName", ("org.kde.secretservicecompat", 0u32));
|
|
- }
|
|
+pub struct Entry(String);
|
|
+pub fn get_entry(user: &str) -> Result<Entry, keyring_core::Error> { Ok(Entry(user.into())) }
|
|
+impl Entry {
|
|
+ pub fn get_secret(&self) -> Result<Vec<u8>, TokenStoreError> { KeychainBackend.get(&self.0)?.ok_or(TokenStoreError::NotFound) }
|
|
+ pub fn set_secret(&self, value: &[u8]) -> Result<(), TokenStoreError> { KeychainBackend.set(&self.0, value) }
|
|
+ pub fn delete_credential(&self) -> Result<(), TokenStoreError> { KeychainBackend.remove(&self.0) }
|
|
}
|
|
-
|
|
-pub fn get_entry(user: &str) -> Result<keyring_core::Entry, keyring_core::Error> {
|
|
- keyring_core::Entry::new(SERVICE_NAME, user)
|
|
-}
|
|
-
|
|
-pub fn destroy_secrets() {
|
|
- keyring_core::unset_default_store();
|
|
-}
|
|
-
|
|
-#[cfg(feature = "key-chain-file")]
|
|
-fn secrets_backing_file() -> std::path::PathBuf {
|
|
- std::env::var_os("HOME")
|
|
- .or_else(|| std::env::var_os("USERPROFILE"))
|
|
- .map(std::path::PathBuf::from)
|
|
- .unwrap_or_else(std::env::temp_dir)
|
|
- .join(".xodus-keyring.ron")
|
|
-}
|
|
+pub fn destroy_secrets() {}
|
|
--- a/crates/xodus/src/tokens/backend/keychain.rs
|
|
+++ b/crates/xodus/src/tokens/backend/keychain.rs
|
|
@@ -1,22 +1,43 @@
|
|
use crate::tokens::store::{TokenBackend, TokenStoreError};
|
|
+use serde_json::{Value, json};
|
|
+use std::io::{BufRead, Read, Write};
|
|
+use std::os::linux::net::SocketAddrExt;
|
|
+use std::os::unix::net::{SocketAddr, UnixStream};
|
|
+use std::time::Duration;
|
|
|
|
pub struct KeychainBackend;
|
|
|
|
+fn request(value: Value) -> Result<Value, TokenStoreError> {
|
|
+ let name = std::env::var("DROIDDECK_XBOX_CREDENTIAL_SOCKET")
|
|
+ .map_err(|_| std::io::Error::other("Android credential host is unavailable"))?;
|
|
+ let address = SocketAddr::from_abstract_name(name)?;
|
|
+ let mut stream = UnixStream::connect_addr(&address)?;
|
|
+ stream.set_read_timeout(Some(Duration::from_secs(10)))?;
|
|
+ stream.set_write_timeout(Some(Duration::from_secs(10)))?;
|
|
+ serde_json::to_writer(&mut stream, &value)?;
|
|
+ stream.write_all(b"\n")?;
|
|
+ let mut bytes = Vec::new();
|
|
+ std::io::BufReader::new(stream).take(2_097_153).read_until(b'\n', &mut bytes)?;
|
|
+ if bytes.len() > 2_097_152 || bytes.last() != Some(&b'\n') {
|
|
+ return Err(std::io::Error::other("Invalid Android credential response").into());
|
|
+ }
|
|
+ let response: Value = serde_json::from_slice(&bytes)?;
|
|
+ if response["ok"] != true { return Err(std::io::Error::other("Android credential storage unavailable").into()); }
|
|
+ Ok(response)
|
|
+}
|
|
+
|
|
impl TokenBackend for KeychainBackend {
|
|
fn get(&self, key: &str) -> Result<Option<Vec<u8>>, TokenStoreError> {
|
|
- let entry = crate::secrets::get_entry(key)?;
|
|
- match entry.get_secret() {
|
|
- Ok(bytes) => Ok(Some(bytes)),
|
|
- Err(keyring_core::Error::NoEntry) => Ok(None),
|
|
- Err(e) => Err(e.into()),
|
|
- }
|
|
+ let response = request(json!({"op":"get", "key":key}))?;
|
|
+ if response["value"].is_null() { return Ok(None); }
|
|
+ Ok(Some(serde_json::from_value(response["value"].clone())?))
|
|
}
|
|
-
|
|
fn set(&self, key: &str, value: &[u8]) -> Result<(), TokenStoreError> {
|
|
- Ok(crate::secrets::get_entry(key)?.set_secret(value)?)
|
|
+ request(json!({"op":"set", "key":key, "value":value}))?;
|
|
+ Ok(())
|
|
}
|
|
-
|
|
fn remove(&self, key: &str) -> Result<(), TokenStoreError> {
|
|
- Ok(crate::secrets::get_entry(key)?.delete_credential()?)
|
|
+ request(json!({"op":"remove", "key":key}))?;
|
|
+ Ok(())
|
|
}
|
|
}
|
|
--- a/crates/xodus/Cargo.toml
|
|
+++ b/crates/xodus/Cargo.toml
|
|
@@ -43,8 +43,8 @@
|
|
smbios-lib = "0.9.4"
|
|
|
|
[target.'cfg(target_os = "linux")'.dependencies]
|
|
-dbus = "=0.9.12"
|
|
-dbus-secret-service-keyring-store = { version = "1.0.1", features = ["crypto-openssl"]}
|
|
+dbus = { version = "=0.9.12", optional = true }
|
|
+dbus-secret-service-keyring-store = { version = "1.0.1", features = ["crypto-openssl"], optional = true}
|
|
|
|
[target.'cfg(target_os = "macos")'.dependencies]
|
|
apple-native-keyring-store = { version = "1.0.2", features = ["keychain"]}
|