Skip to content

Commit

Permalink
client: Return Secret instead of a blob
Browse files Browse the repository at this point in the history
Makes uses of the content-type from the DBus API and just hack
around for the portal backend until we figure out whether
it makes sense to store the content-type as an attribute
  • Loading branch information
bilelmoussaoui committed Nov 2, 2024
1 parent b600ead commit 7c548c8
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 27 deletions.
4 changes: 2 additions & 2 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,9 @@ async fn print_item<'a>(
as_hex: bool,
) -> Result<(), Error> {
use std::fmt::Write;
let secret = item.secret().await?;
let bytes = secret.as_bytes();
if secret_only {
let bytes = item.secret().await?;
let mut stdout = std::io::stdout().lock();
if as_hex {
let hex = hex::encode(&bytes);
Expand All @@ -260,7 +261,6 @@ async fn print_item<'a>(
}
} else {
let label = item.label().await?;
let bytes = item.secret().await?;
let mut attributes = item.attributes().await?;
let created = item.created().await?;
let modified = item.modified().await?;
Expand Down
16 changes: 16 additions & 0 deletions client/src/dbus/api/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,22 @@ impl<'a> DBusSecret<'a> {
})
}

pub(crate) fn decrypt(&self, key: Option<&Arc<Key>>) -> Result<Secret, Error> {
let value = match key {
Some(key) => &crypto::decrypt(&self.value, &key, &self.parameters),
None => &self.value,
};

match self.content_type.as_str() {
"text/plain" => Ok(Secret::Text(String::from_utf8(value.to_vec())?)),
"application/octet-stream" => Ok(Secret::blob(value)),
e => {
tracing::warn!("Unsupported content-type {e}, falling back to blob");
Ok(Secret::blob(value))
}
}
}

/// Session used to encode the secret
pub fn session(&self) -> &Session {
&self.session
Expand Down
4 changes: 2 additions & 2 deletions client/src/dbus/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ mod tests {
"plain-type-test"
};
attributes.insert("type", value);
let secret = "a password";
let secret = crate::Secret::text("a password");

let collection = service.default_collection().await.unwrap();
let n_items = collection.items().await.unwrap().len();
Expand All @@ -280,7 +280,7 @@ mod tests {
.await
.unwrap();

assert_eq!(*item.secret().await.unwrap(), secret.as_bytes());
assert_eq!(*item.secret().await.unwrap(), secret);
assert_eq!(item.attributes().await.unwrap()["type"], value);

assert_eq!(collection.items().await.unwrap().len(), n_items + 1);
Expand Down
11 changes: 10 additions & 1 deletion client/src/dbus/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::fmt;
use std::{fmt, string::FromUtf8Error};

/// DBus Secret Service specific errors.
/// <https://specifications.freedesktop.org/secret-service-spec/latest/errors.html>
Expand Down Expand Up @@ -31,6 +31,8 @@ pub enum Error {
NotFound(String),
/// Input/Output.
IO(std::io::Error),
/// Secret to string conversion failure.
Utf8(FromUtf8Error),
}

impl From<zbus::Error> for Error {
Expand Down Expand Up @@ -63,6 +65,12 @@ impl From<std::io::Error> for Error {
}
}

impl From<FromUtf8Error> for Error {
fn from(value: FromUtf8Error) -> Self {
Self::Utf8(value)
}
}

impl std::error::Error for Error {}

impl fmt::Display for Error {
Expand All @@ -74,6 +82,7 @@ impl fmt::Display for Error {
Self::Deleted => write!(f, "Item/Collection was deleted, can no longer be used"),
Self::NotFound(name) => write!(f, "The collection '{name}' doesn't exists"),
Self::Dismissed => write!(f, "Prompt was dismissed"),
Self::Utf8(e) => write!(f, "Failed to convert a text/plain secret to string, {e}"),
}
}
}
22 changes: 6 additions & 16 deletions client/src/dbus/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ use async_lock::RwLock;
#[cfg(feature = "tokio")]
use tokio::sync::RwLock;
use zbus::zvariant::ObjectPath;
use zeroize::Zeroizing;

use super::{api, Algorithm, Error};
use crate::{crypto, AsAttributes, Key, Secret};
use crate::{AsAttributes, Key, Secret};

/// A secret with a label and attributes to identify it.
///
Expand Down Expand Up @@ -134,23 +133,14 @@ impl<'a> Item<'a> {
}

/// Retrieve the currently stored secret.
pub async fn secret(&self) -> Result<Zeroizing<Vec<u8>>, Error> {
pub async fn secret(&self) -> Result<Secret, Error> {
if !self.is_available().await {
Err(Error::Deleted)
} else {
let secret = self.inner.secret(&self.session).await?;

let value = match self.algorithm {
Algorithm::Plain => Zeroizing::new(secret.value.to_owned()),
Algorithm::Encrypted => {
let iv = &secret.parameters;
// Safe unwrap as it is encrypted
let aes_key = self.aes_key.as_ref().unwrap();

crypto::decrypt(&secret.value, aes_key, iv)
}
};
Ok(value)
self.inner
.secret(&self.session)
.await?
.decrypt(self.aes_key.as_ref())
}
}

Expand Down
3 changes: 1 addition & 2 deletions client/src/keyring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::{collections::HashMap, sync::Arc, time::Duration};
use async_lock::RwLock;
#[cfg(feature = "tokio")]
use tokio::sync::RwLock;
use zeroize::Zeroizing;

use crate::{dbus, portal, AsAttributes, Result, Secret};

Expand Down Expand Up @@ -265,7 +264,7 @@ impl Item {
}

/// Retrieves the stored secret.
pub async fn secret(&self) -> Result<Zeroizing<Vec<u8>>> {
pub async fn secret(&self) -> Result<Secret> {
let secret = match self {
Self::File(item, _) => item.read().await.secret(),
Self::DBus(item) => item.secret().await?,
Expand Down
4 changes: 2 additions & 2 deletions client/src/portal/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ impl Item {
}

/// Retrieve the currently stored secret.
pub fn secret(&self) -> Zeroizing<Vec<u8>> {
Zeroizing::new(self.secret.clone())
pub fn secret(&self) -> Secret {
Secret::blob(&self.secret)
}

/// Store a new secret.
Expand Down
3 changes: 1 addition & 2 deletions client/src/portal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ use tokio::{
io::AsyncReadExt,
sync::{Mutex, RwLock},
};
use zeroize::Zeroizing;

use crate::{AsAttributes, Key, Secret};

Expand All @@ -66,7 +65,7 @@ mod item;
pub use error::{Error, InvalidItemError, WeakKeyError};
pub use item::Item;

type ItemDefinition = (String, HashMap<String, String>, Zeroizing<Vec<u8>>, bool);
type ItemDefinition = (String, HashMap<String, String>, Secret, bool);

/// File backed keyring.
#[derive(Debug)]
Expand Down

0 comments on commit 7c548c8

Please sign in to comment.