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
12 changes: 6 additions & 6 deletions client/src/dbus/api/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
use super::Session;
use crate::{Key, Secret, crypto, dbus::Error, secret::ContentType};

#[derive(Debug, Serialize, Deserialize, Type)]
#[derive(Debug, Serialize, Deserialize, Type, Zeroize, ZeroizeOnDrop)]
#[zvariant(signature = "(oayays)")]
/// Same as [`DBusSecret`] without tying the session path to a [`Session`] type.
pub struct DBusSecretInner(
pub OwnedObjectPath,
#[zeroize(skip)] pub OwnedObjectPath,
#[serde(with = "serde_bytes")] pub Vec<u8>,
#[serde(with = "serde_bytes")] pub Vec<u8>,
pub ContentType,
#[zeroize(skip)] pub ContentType,
);

#[derive(Debug, Type, Zeroize, ZeroizeOnDrop)]
Expand Down Expand Up @@ -58,9 +58,9 @@ impl DBusSecret {

pub async fn from_inner(cnx: &zbus::Connection, inner: DBusSecretInner) -> Result<Self, Error> {
Ok(Self {
session: Arc::new(Session::new(cnx, inner.0).await?),
parameters: inner.1,
value: inner.2,
session: Arc::new(Session::new(cnx, inner.0.clone()).await?),
parameters: inner.1.clone(),
value: inner.2.clone(),
content_type: inner.3,
})
}
Expand Down
4 changes: 3 additions & 1 deletion client/src/file/api/encrypted_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ use std::collections::HashMap;

use serde::{Deserialize, Serialize};
use zbus::zvariant::Type;
use zeroize::{Zeroize, ZeroizeOnDrop};

use super::{Error, UnlockedItem};
use crate::{Key, Mac, crypto};

#[derive(Deserialize, Serialize, Type, Debug, Clone)]
#[derive(Deserialize, Serialize, Type, Debug, Clone, Zeroize, ZeroizeOnDrop)]
pub(crate) struct EncryptedItem {
#[zeroize(skip)]
pub(crate) hashed_attributes: HashMap<String, Mac>,
#[serde(with = "serde_bytes")]
pub(crate) blob: Vec<u8>,
Expand Down
3 changes: 2 additions & 1 deletion client/src/file/api/legacy_keyring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{
};

use endi::{Endian, ReadBytes};
use zeroize::{Zeroize, ZeroizeOnDrop};

use super::{Secret, UnlockedItem};
use crate::{
Expand All @@ -19,7 +20,7 @@ const FILE_HEADER_LEN: usize = FILE_HEADER.len();
pub const MAJOR_VERSION: u8 = 0;
pub const MINOR_VERSION: u8 = 0;

#[derive(Debug)]
#[derive(Debug, Zeroize, ZeroizeOnDrop)]
pub struct Keyring {
salt: Vec<u8>,
iteration_count: u32,
Expand Down
4 changes: 3 additions & 1 deletion client/src/file/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ mod legacy_keyring;

pub(super) use encrypted_item::EncryptedItem;
pub(super) use legacy_keyring::{Keyring as LegacyKeyring, MAJOR_VERSION as LEGACY_MAJOR_VERSION};
use zeroize::{Zeroize, ZeroizeOnDrop};

use crate::{
AsAttributes, Key, Secret, crypto,
Expand All @@ -67,14 +68,15 @@ pub(crate) static GVARIANT_ENCODING: LazyLock<Context> =
LazyLock::new(|| Context::new_gvariant(Endian::Little, 0));

/// Logical contents of a keyring file
#[derive(Deserialize, Serialize, Type, Debug)]
#[derive(Deserialize, Serialize, Type, Debug, Zeroize, ZeroizeOnDrop)]
pub struct Keyring {
salt_size: u32,
#[serde(with = "serde_bytes")]
salt: Vec<u8>,
iteration_count: u32,
modified_time: u64,
usage_count: u32,
#[zeroize(skip)]
pub(in crate::file) items: Vec<EncryptedItem>,
}

Expand Down
3 changes: 2 additions & 1 deletion client/src/mac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ use serde::{Deserialize, Serialize};
#[cfg(feature = "native_crypto")]
use subtle::ConstantTimeEq;
use zbus::zvariant::Type;
use zeroize::{Zeroize, ZeroizeOnDrop};

// There is no constructor to avoid performing sanity checks, e.g. length.
/// A message authentication code. It provides constant-time comparison when
/// compared against another mac or against a slice of bytes.
#[derive(Deserialize, Serialize, Type, Clone)]
#[derive(Deserialize, Serialize, Type, Clone, Zeroize, ZeroizeOnDrop)]
pub struct Mac(#[serde(with = "serde_bytes")] Vec<u8>);

impl std::fmt::Debug for Mac {
Expand Down
2 changes: 1 addition & 1 deletion server/src/capability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fn set_bounding_set(caps: CapabilitySet) -> Result<(), rustix::io::Errno> {
Ok(())
}

#[derive(Debug, PartialEq)]
#[derive(PartialEq)]
enum CapabilityState {
Full, // setuid root or root user
Partial, // filesystem-based capabilities
Expand Down
10 changes: 5 additions & 5 deletions server/src/collection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::{
item,
};

#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct Collection {
// Properties
items: Arc<Mutex<Vec<item::Item>>>,
Expand Down Expand Up @@ -225,22 +225,22 @@ impl Collection {
let keyring = self.keyring.read().await;
let keyring = keyring.as_ref().unwrap().as_unlocked();

let DBusSecretInner(session_path, iv, secret_bytes, content_type) = secret;
let DBusSecretInner(ref session_path, ref iv, ref secret_bytes, ref content_type) = secret;
let label = properties.label();
// Safe to unwrap as an item always has attributes
let mut attributes = properties.attributes().unwrap().to_owned();

let Some(session) = self.service.session(&session_path).await else {
let Some(session) = self.service.session(session_path).await else {
tracing::error!("The session `{}` does not exist.", session_path);
return Err(ServiceError::NoSession(format!(
"The session `{session_path}` does not exist."
)));
};

let secret = match session.aes_key() {
Some(key) => oo7::crypto::decrypt(secret_bytes, &key, &iv)
Some(key) => oo7::crypto::decrypt(secret_bytes, &key, iv)
.map_err(|err| custom_service_error(&format!("Failed to decrypt secret {err}.")))?,
None => zeroize::Zeroizing::new(secret_bytes),
None => zeroize::Zeroizing::new(secret_bytes.clone()),
};

// Ensure content-type attribute is stored
Expand Down
2 changes: 1 addition & 1 deletion server/src/gnome/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::{
pub const INTERNAL_INTERFACE_PATH: &str =
"/org/gnome/keyring/InternalUnsupportedGuiltRiddenInterface";

#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct InternalInterface {
service: Service,
}
Expand Down
6 changes: 3 additions & 3 deletions server/src/gnome/prompter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ mod double_value_optional {
}
}

#[derive(Debug, Serialize, Deserialize, Type, Default)]
#[derive(Serialize, Deserialize, Type, Default)]
#[zvariant(signature = "dict")]
#[serde(rename_all = "kebab-case")]
// GcrPrompt properties <https://gitlab.gnome.org/GNOME/gcr/-/blob/main/gcr/gcr-prompt.c#L95>
Expand Down Expand Up @@ -226,7 +226,7 @@ impl TryFrom<String> for Reply {
}
}

#[derive(Deserialize, Serialize, Debug, Type, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Deserialize, Serialize, Type, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "lowercase")]
#[zvariant(signature = "s")]
pub enum PromptType {
Expand Down Expand Up @@ -254,7 +254,7 @@ pub trait GNOMEPrompter {
fn stop_prompting(&self, callback: &ObjectPath<'_>) -> Result<(), ServiceError>;
}

#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct GNOMEPrompterCallback {
window_id: Option<WindowIdentifierType>,
private_key: Arc<Key>,
Expand Down
8 changes: 4 additions & 4 deletions server/src/item/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use zbus::zvariant::{ObjectPath, OwnedObjectPath};

use crate::{Service, collection::Collection, error::custom_service_error};

#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct Item {
// Properties
pub(super) inner: Arc<Mutex<Option<oo7::file::Item>>>,
Expand Down Expand Up @@ -139,9 +139,9 @@ impl Item {
}

pub async fn set_secret(&self, secret: DBusSecretInner) -> Result<(), ServiceError> {
let DBusSecretInner(session, iv, secret, content_type) = secret;
let DBusSecretInner(ref session, ref iv, ref secret, ref content_type) = secret;

let Some(session) = self.service.session(&session).await else {
let Some(session) = self.service.session(session).await else {
tracing::error!("The session `{}` does not exist.", session);
return Err(ServiceError::NoSession(format!(
"The session `{session}` does not exist."
Expand All @@ -162,7 +162,7 @@ impl Item {

match session.aes_key() {
Some(key) => {
let decrypted = oo7::crypto::decrypt(secret, &key, &iv).map_err(|err| {
let decrypted = oo7::crypto::decrypt(secret, &key, iv).map_err(|err| {
custom_service_error(&format!("Failed to decrypt secret {err}."))
})?;
inner.as_mut_unlocked().set_secret(decrypted);
Expand Down
2 changes: 1 addition & 1 deletion server/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use oo7::{Secret, file::UnlockedKeyring};
use crate::error::Error;

/// Pending keyring migration
#[derive(Clone, Debug)]
#[derive(Clone)]
pub enum PendingMigration {
/// Legacy v0 keyring format
V0 {
Expand Down
2 changes: 1 addition & 1 deletion server/src/pam_listener/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ enum PamOperation {
ChangePassword = 1,
}

#[derive(Debug, Serialize, Deserialize, Type, Zeroize, ZeroizeOnDrop)]
#[derive(Serialize, Deserialize, Type, Zeroize, ZeroizeOnDrop)]
struct PamMessage {
#[zeroize(skip)]
operation: PamOperation,
Expand Down
4 changes: 2 additions & 2 deletions server/src/plasma/prompter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{
};

#[repr(i32)]
#[derive(Debug, Type, Serialize)]
#[derive(Type, Serialize)]
pub enum CallbackAction {
Dismiss = 0,
Keep = 1,
Expand Down Expand Up @@ -77,7 +77,7 @@ pub trait PlasmaPrompter {
) -> Result<(), ServiceError>;
}

#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct PlasmaPrompterCallback {
service: Service,
prompt_path: OwnedObjectPath,
Expand Down
26 changes: 6 additions & 20 deletions server/src/prompt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,6 @@ pub struct Prompt {
action: Arc<Mutex<Option<PromptAction>>>,
}

// Manual impl because OnceCell doesn't impl Debug
impl std::fmt::Debug for Prompt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Prompt")
.field("service", &self.service)
.field("role", &self.role)
.field("path", &self.path)
.field("label", &self.label)
.field("collection", &self.collection)
.finish()
}
}

#[cfg(any(
feature = "gnome_openssl_crypto",
feature = "gnome_native_crypto",
Expand All @@ -114,9 +101,9 @@ impl Prompt {
PlasmaPrompterCallback::new(self.service.clone(), self.path.clone()).await;
let path = OwnedObjectPath::from(callback.path().clone());

self.plasma_callback
.set(callback.clone())
.expect("A prompt callback is only set once");
// We are sure the callback is not set at this point, so it is fine to ignore
// the result of set
let _ = self.plasma_callback.set(callback.clone());
self.service
.object_server()
.at(&path, callback.clone())
Expand Down Expand Up @@ -147,10 +134,9 @@ impl Prompt {

let path = OwnedObjectPath::from(callback.path().clone());

self.gnome_callback
.set(callback.clone())
.expect("A prompt callback is only set once");

// We are sure the callback is not set at this point, so it is fine to ignore
// the result of set
let _ = self.gnome_callback.set(callback.clone());
self.service.object_server().at(&path, callback).await?;
tracing::debug!("Prompt `{}` created.", self.path);

Expand Down
4 changes: 2 additions & 2 deletions server/src/service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ const DEFAULT_COLLECTION_ALIAS_PATH: ObjectPath<'static> =
ObjectPath::from_static_str_unchecked("/org/freedesktop/secrets/aliases/default");

/// Prompter type
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum PrompterType {
#[allow(clippy::upper_case_acronyms)]
GNOME,
Plasma,
}

#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct Service {
// Properties
pub(crate) collections: Arc<Mutex<HashMap<OwnedObjectPath, Collection>>>,
Expand Down
2 changes: 1 addition & 1 deletion server/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use zbus::{

use crate::Service;

#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct Session {
aes_key: Option<Arc<Key>>,
service: Service,
Expand Down
4 changes: 2 additions & 2 deletions server/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ impl TestServiceSetup {
/// This simulates the GNOME System Prompter for testing without requiring
/// the actual GNOME keyring prompter service to be running.
#[cfg(any(feature = "gnome_native_crypto", feature = "gnome_openssl_crypto"))]
#[derive(Debug, Clone)]
#[derive(Clone)]
pub(crate) struct MockPrompterService {
/// The password to use for unlock prompts (simulates user input)
unlock_password: Arc<tokio::sync::Mutex<Option<oo7::Secret>>>,
Expand Down Expand Up @@ -634,7 +634,7 @@ impl MockPrompterService {
/// This simulates the Plasma System Prompter for testing without requiring
/// the actual service to be running.
#[cfg(any(feature = "plasma_native_crypto", feature = "plasma_openssl_crypto"))]
#[derive(Debug, Clone)]
#[derive(Clone)]
pub(crate) struct MockPrompterServicePlasma {
/// The password to use for unlock prompts (simulates user input)
unlock_password: Arc<tokio::sync::Mutex<Option<oo7::Secret>>>,
Expand Down
Loading