Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 2 additions & 19 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,6 @@ jobs:
run: |
cargo build --manifest-path ./portal/Cargo.toml

- name: Setup D-Bus and Secret Service for local tests
run: |
sudo apt-get update
sudo apt-get install -y gnome-keyring dbus-x11

# Start D-Bus session
mkdir -p ~/.local/share/keyrings
eval $(dbus-launch --sh-syntax)
export DBUS_SESSION_BUS_ADDRESS
echo "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" >> $GITHUB_ENV

# Initialize and unlock the default keyring
printf '\n' | gnome-keyring-daemon --unlock --daemonize --login

# Give the service time to start
sleep 3

- name: Test (native)
run: |
cargo test --manifest-path ./client/Cargo.toml --no-default-features --features tokio --features native_crypto --features schema
Expand Down Expand Up @@ -111,11 +94,11 @@ jobs:
with:
components: clippy
- name: Clippy workspace (default features)
run: cargo clippy --workspace -- -D warnings
run: cargo clippy --workspace --tests -- -D warnings
- name: Clippy client (tracing / async-std / native crypto)
run: cargo clippy -p oo7 --no-default-features --features tracing,async-std,native_crypto,schema -- -D warnings
- name: Clippy client (tracing / tokio / OpenSSL)
run: cargo clippy -p oo7 --no-default-features --features tracing,tokio,openssl_crypto,schema -- -D warnings
run: cargo clippy -p oo7 --no-default-features --features tracing,tokio,openssl_crypto,schema --tests -- -D warnings

meson:
name: Meson
Expand Down
17 changes: 0 additions & 17 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,6 @@ jobs:
with:
tool: grcov

- name: Install system dependencies and setup D-Bus
run: |
sudo apt-get update
sudo apt-get install -y libssl-dev pkg-config gnome-keyring dbus-x11 jq
# Start D-Bus session
mkdir -p ~/.local/share/keyrings
eval $(dbus-launch --sh-syntax)
export DBUS_SESSION_BUS_ADDRESS
echo "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" >> $GITHUB_ENV
# Initialize and unlock the default keyring
printf '\n' | gnome-keyring-daemon --unlock --daemonize --login
# Give the service time to start
sleep 3
- name: Run coverage script
run: |
chmod +x coverage.sh
Expand Down
55 changes: 1 addition & 54 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ zvariant.workspace = true
zeroize.workspace = true

[dev-dependencies]
serial_test = "3.4"
oo7-daemon = { path = "../server", features = ["test-util"], default-features = false, version = "0.6.0-alpha" }
tempfile.workspace = true
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] }
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
Expand All @@ -74,8 +74,12 @@ native_crypto = [
"dep:pbkdf2",
"dep:sha2",
"dep:subtle",
"oo7-daemon/native_crypto",
]
openssl_crypto = [
"dep:openssl",
"oo7-daemon/openssl_crypto",
]
openssl_crypto = ["dep:openssl"]
tracing = ["dep:tracing", "ashpd/tracing"]
schema = ["dep:oo7-macros"]

Expand Down
53 changes: 43 additions & 10 deletions client/src/dbus/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,25 @@ impl Service {
/// Create a new instance of the Service, an encrypted communication would
/// be attempted first and would fall back to a plain one if that fails.
pub async fn new() -> Result<Self, Error> {
let service = match Self::encrypted().await {
let cnx = zbus::connection::Builder::session()?
.method_timeout(std::time::Duration::from_secs(30))
.build()
.await?;
Self::new_with_connection(&cnx).await
}

/// Create a new instance of the Service with a custom connection.
///
/// An encrypted communication would be attempted first and would fall back
/// to a plain one if that fails.
pub async fn new_with_connection(cnx: &zbus::Connection) -> Result<Self, Error> {
let service = match Self::encrypted_with_connection(cnx).await {
Ok(service) => Ok(service),
Err(Error::ZBus(zbus::Error::MethodError(..))) => Self::plain().await,
Err(Error::ZBus(zbus::Error::MethodError(..))) => {
Self::plain_with_connection(cnx).await
}
Err(Error::Service(ServiceError::ZBus(zbus::Error::MethodError(..)))) => {
Self::plain().await
Self::plain_with_connection(cnx).await
}
Err(e) => Err(e),
}?;
Expand All @@ -62,22 +76,41 @@ impl Service {

/// Create a new instance of the Service with plain algorithm.
pub async fn plain() -> Result<Self, Error> {
Self::with_algorithm(Algorithm::Plain).await
let cnx = zbus::connection::Builder::session()?
.method_timeout(std::time::Duration::from_secs(30))
.build()
.await?;
Self::plain_with_connection(&cnx).await
}

/// Create a new instance of the Service with encrypted algorithm.
pub async fn encrypted() -> Result<Self, Error> {
Self::with_algorithm(Algorithm::Encrypted).await
/// Create a new instance of the Service with plain algorithm and a custom
/// connection.
pub async fn plain_with_connection(cnx: &zbus::Connection) -> Result<Self, Error> {
Self::with_algorithm_and_connection(Algorithm::Plain, cnx).await
}

/// Create a new instance of the Service.
async fn with_algorithm(algorithm: Algorithm) -> Result<Self, Error> {
/// Create a new instance of the Service with encrypted algorithm.
pub async fn encrypted() -> Result<Self, Error> {
let cnx = zbus::connection::Builder::session()?
.method_timeout(std::time::Duration::from_secs(30))
.build()
.await?;
Self::encrypted_with_connection(&cnx).await
}

/// Create a new instance of the Service with encrypted algorithm and a
/// custom connection.
pub async fn encrypted_with_connection(cnx: &zbus::Connection) -> Result<Self, Error> {
Self::with_algorithm_and_connection(Algorithm::Encrypted, cnx).await
}

let service = Arc::new(api::Service::new(&cnx).await?);
/// Create a new instance of the Service with a specific algorithm and
/// connection.
async fn with_algorithm_and_connection(
algorithm: Algorithm,
cnx: &zbus::Connection,
) -> Result<Self, Error> {
let service = Arc::new(api::Service::new(cnx).await?);

let (aes_key, session) = match algorithm {
Algorithm::Plain => {
Expand Down
18 changes: 18 additions & 0 deletions client/src/file/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,24 @@ impl Keyring {
}
}

/// Construct a keyring path within a specific data directory.
///
/// This is useful for tests and cases where you want explicit control over
/// where keyrings are stored, avoiding the default XDG_DATA_HOME location.
pub(crate) fn path_at(
data_dir: impl AsRef<std::path::Path>,
name: &str,
version: u8,
) -> PathBuf {
let mut path = data_dir.as_ref().to_path_buf();
path.push("keyrings");
if version > 0 {
path.push(format!("v{version}"));
}
path.push(format!("{name}.keyring"));
path
}

pub fn default_path() -> Result<PathBuf, Error> {
Self::path("default", LEGACY_MAJOR_VERSION)
}
Expand Down
16 changes: 16 additions & 0 deletions client/src/file/locked_keyring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,20 @@ impl LockedKeyring {
let v1_path = api::Keyring::path(name, api::MAJOR_VERSION)?;
Self::load(v1_path).await
}

/// Open a locked keyring at a specific data directory.
///
/// This is useful for tests and cases where you want explicit control over
/// where keyrings are stored, avoiding the default XDG_DATA_HOME location.
///
/// # Arguments
///
/// * `data_dir` - Base data directory (keyrings stored in
/// `data_dir/keyrings/v1/`)
/// * `name` - The name of the keyring.
#[cfg_attr(feature = "tracing", tracing::instrument(fields(data_dir = ?data_dir.as_ref())))]
pub async fn open_at(data_dir: impl AsRef<std::path::Path>, name: &str) -> Result<Self, Error> {
let path = api::Keyring::path_at(data_dir, name, api::MAJOR_VERSION);
Self::load(path).await
}
}
Loading
Loading