Files
DroidDeck/tools/xbox/droiddeck-credentials.patch
T

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"]}