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
8 changes: 4 additions & 4 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,8 @@ impl Commands {
"Only one of application ID or keyring can be specified at a time.",
));
}
// We get the secret first from the app-id, then if the --keyring is set, we try
// to use the --secret variable.
// We get the secret first from the app-id, then if the --keyring is
// set, we try to use the --secret variable.
let (secret, path) = if let Some(app_id) = &args.app_id {
let default_collection = service.default_collection().await?;
let secret = if let Some(item) = default_collection
Expand All @@ -438,8 +438,8 @@ impl Commands {
));
};

// That is the path used by libsecret/oo7, how does it work with kwallet for
// example?
// That is the path used by libsecret/oo7, how does it work with
// kwallet for example?
let path = home().map(|mut path| {
path.push(".var/app");
path.push(app_id.to_string());
Expand Down
4 changes: 2 additions & 2 deletions client/src/file/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,8 @@ impl Keyring {
pub fn validate_secret(&self, secret: &Secret) -> Result<bool, crypto::Error> {
let key = self.derive_key(secret)?;

// If there are no items, we can't validate (empty keyrings are valid with any
// password)
// If there are no items, we can't validate (empty keyrings are valid
// with any password)
if self.items.is_empty() {
return Ok(true);
}
Expand Down
3 changes: 2 additions & 1 deletion client/src/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ impl FromStr for ContentType {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
// MIME types may include parameters, which are irrelevant to ContentType.
// MIME types may include parameters, which are irrelevant to
// ContentType.
let media_type = s
.split_once(';')
.map_or(s, |(media_type, _)| media_type)
Expand Down
10 changes: 6 additions & 4 deletions client/tests/file_unlocked_keyring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,8 +535,8 @@ async fn delete_broken_items() -> Result<(), Error> {
let keyring_path = v1_dir.join("default.keyring");
fs::copy(&fixture_path, &keyring_path).await?;

// 1) Load with the correct password and add several valid items. This ensures
// valid_items > broken_items that we'll add later.
// 1) Load with the correct password and add several valid items. This
// ensures valid_items > broken_items that we'll add later.
let keyring = UnlockedKeyring::load(&keyring_path, Some(Secret::blob("test"))).await?;
for i in 0..VALID_TO_ADD {
keyring
Expand Down Expand Up @@ -1201,7 +1201,8 @@ async fn partially_corrupted_keyring_error() -> Result<(), Error> {
let key = key.as_ref().as_ref().to_vec();
drop(keyring);

// Load_unchecked with wrong password and add 3 broken items (more than valid)
// Load_unchecked with wrong password and add 3 broken items (more than
// valid)
let wrong_secret = Secret::from("wrong-password-long-enough".as_bytes());
let keyring = unsafe { UnlockedKeyring::load_unchecked(&keyring_path, wrong_secret).await? };
keyring
Expand Down Expand Up @@ -1329,7 +1330,8 @@ async fn set_attributes() -> Result<(), Error> {
// Write the updated item back to the keyring at index 0
keyring.replace_item_index(0, &item).await?;

// Now retrieve the item again from the keyring to verify the changes persisted
// Now retrieve the item again from the keyring to verify the changes
// persisted
let mut items = keyring.items().await?;
assert_eq!(items.len(), 1);
let item = items.remove(0);
Expand Down
12 changes: 3 additions & 9 deletions pam/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{
socket::send_secret_to_daemon,
};

const STASHED_PASSWORD_KEY: &[u8] = b"oo7_stashed_password\0";
const STASHED_PASSWORD_KEY: &CStr = c"oo7_stashed_password";

/// Get the username
unsafe fn get_user(pamh: *mut pam_handle_t) -> Result<String, c_int> {
Expand Down Expand Up @@ -164,7 +164,7 @@ pub unsafe extern "C" fn pam_sm_authenticate(
let ret = unsafe {
ffi::pam_set_data(
pamh,
STASHED_PASSWORD_KEY.as_ptr() as *const std::os::raw::c_char,
STASHED_PASSWORD_KEY.as_ptr(),
password_ptr,
Some(cleanup_password),
)
Expand Down Expand Up @@ -238,13 +238,7 @@ pub unsafe extern "C" fn pam_sm_open_session(
}

let mut password_ptr: *const std::os::raw::c_void = std::ptr::null();
let ret = unsafe {
ffi::pam_get_data(
pamh,
STASHED_PASSWORD_KEY.as_ptr() as *const std::os::raw::c_char,
&mut password_ptr,
)
};
let ret = unsafe { ffi::pam_get_data(pamh, STASHED_PASSWORD_KEY.as_ptr(), &mut password_ptr) };

if ret != PAM_SUCCESS || password_ptr.is_null() {
tracing::debug!("No stashed password found in session");
Expand Down
11 changes: 7 additions & 4 deletions server/src/capability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ pub fn drop_unnecessary_capabilities() -> Result<(), rustix::io::Errno> {
tracing::warn!("Failed to set PR_SET_KEEPCAPS");
}

// Requires CAP_SETPCAP -> must run before reducing the bounding set drops it
// Requires CAP_SETPCAP -> must run before reducing the bounding set
// drops it
if let Err(err) = set_bounding_set(CapabilitySet::IPC_LOCK) {
tracing::debug!("Could not set bounding set (may not be supported): {}", err);
}
Expand All @@ -126,8 +127,9 @@ pub fn drop_unnecessary_capabilities() -> Result<(), rustix::io::Errno> {
)?;
}
CapabilityState::None => {
// CAP_IPC_LOCK bypasses RLIMIT_MEMLOCK, but is not required when the
// process has a sufficient limit. Always try mlockall below.
// CAP_IPC_LOCK bypasses RLIMIT_MEMLOCK, but is not required when
// the process has a sufficient limit. Always try
// mlockall below.
tracing::warn!("No process capabilities; relying on RLIMIT_MEMLOCK to lock memory");
}
CapabilityState::Partial => {
Expand All @@ -139,7 +141,8 @@ pub fn drop_unnecessary_capabilities() -> Result<(), rustix::io::Errno> {
);
}

// Clear bounding set if we have CAP_SETPCAP (do this before dropping caps)
// Clear bounding set if we have CAP_SETPCAP (do this before
// dropping caps)
if caps.effective.contains(CapabilitySet::SETPCAP)
&& let Err(err) = set_bounding_set(CapabilitySet::IPC_LOCK)
{
Expand Down
3 changes: 2 additions & 1 deletion server/src/collection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,8 @@ impl Collection {
let unlocked = match unlock_result {
Ok(unlocked) => unlocked,
Err(err) => {
// Reload the locked keyring from disk before returning error
// Reload the locked keyring from disk before
// returning error
if let Some(path) = keyring_path
&& let Ok(reloaded) = oo7::file::LockedKeyring::load(&path).await
{
Expand Down
3 changes: 2 additions & 1 deletion server/src/collection/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ async fn create_item_plain() -> Result<(), Box<dyn std::error::Error>> {
async fn create_item_encrypted() -> Result<(), Box<dyn std::error::Error>> {
let setup = TestServiceSetup::encrypted_session(true).await?;

// Create an encrypted item using the helper (automatically handles encryption)
// Create an encrypted item using the helper (automatically handles
// encryption)
let item = setup
.create_item(
"Test Encrypted Item",
Expand Down
9 changes: 6 additions & 3 deletions server/src/gnome/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,8 @@ mod tests {
)
.await?;

// Verify the password was changed by locking and unlocking with new password
// Verify the password was changed by locking and unlocking with new
// password
setup
.service_api
.lock(std::slice::from_ref(&collection_path), None)
Expand Down Expand Up @@ -428,7 +429,8 @@ mod tests {
// Wait for prompt to complete
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;

// Verify the password was changed by locking and unlocking with new password
// Verify the password was changed by locking and unlocking with new
// password
setup
.service_api
.lock(std::slice::from_ref(&collection_path), None)
Expand Down Expand Up @@ -463,7 +465,8 @@ mod tests {
let collection_path: zbus::zvariant::OwnedObjectPath =
default_collection.inner().path().to_owned().into();

// Create an item first so that the unlock validation has something to validate
// Create an item first so that the unlock validation has something to
// validate
let dbus_secret = setup.create_dbus_secret("item-secret")?;

let mut attributes = std::collections::HashMap::new();
Expand Down
3 changes: 2 additions & 1 deletion server/src/gnome/prompter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,8 @@ impl GNOMEPrompterCallback {
Some(raw_secret)
};

// Handle each role differently based on what validation/preparation is needed
// Handle each role differently based on what validation/preparation is
// needed
match prompt.role() {
PromptRole::Unlock => {
if prompt.on_unlock_collection(secret).await? {
Expand Down
5 changes: 3 additions & 2 deletions server/src/gnome/secret_exchange.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ pub fn handshake(private_key: &Key, exchange: &str) -> Result<Key, crypto::Error
pub fn retrieve(exchange: &str, aes_key: &Key) -> Option<oo7::Secret> {
let decoded = decode(exchange)?;

// If we cancel an ongoing prompt call, the final exchange won't have the secret
// or IV. The following is to avoid `Option::unwrap()` on a `None` value
// If we cancel an ongoing prompt call, the final exchange won't have the
// secret or IV. The following is to avoid `Option::unwrap()` on a
// `None` value
let secret = decoded.get(SECRET)?;

// AES ciphertext must be a multiple of 16 bytes (block size)
Expand Down
3 changes: 2 additions & 1 deletion server/src/pam_listener/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,8 @@ impl PamListener {
tracing::info!("Successfully changed password for collection: {}", path);
changed_count += 1;

// Re-lock the collection if it was locked before we unlocked it
// Re-lock the collection if it was locked before we
// unlocked it
drop(keyring_guard);
if was_locked {
if let Err(e) = collection.set_locked(true, None).await {
Expand Down
3 changes: 2 additions & 1 deletion server/src/plasma/prompter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ impl PlasmaPrompterCallback {
prompt: &Prompt,
secret: Option<Secret>,
) -> Result<CallbackAction, ServiceError> {
// Handle each role differently based on what validation/preparation is needed
// Handle each role differently based on what validation/preparation is
// needed
match prompt.role() {
PromptRole::Unlock => {
if prompt.on_unlock_collection(secret).await? {
Expand Down
6 changes: 4 additions & 2 deletions server/src/prompt/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ async fn prompt_called_twice_error_impl(
// Give the prompt a moment to register the callback
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;

// Second call to prompt() should fail with "callback is ongoing already" error
// Second call to prompt() should fail with "callback is ongoing already"
// error
assert!(
prompt.prompt(None).await.is_err(),
"Second call to prompt() should fail"
Expand Down Expand Up @@ -66,7 +67,8 @@ async fn prompt_not_found_error() -> Result<(), Box<dyn std::error::Error>> {

assert!(!prompt_path.is_empty(), "Should have a prompt path");

// Remove the prompt from the service before MockPrompter tries to process it
// Remove the prompt from the service before MockPrompter tries to process
// it
setup.server.remove_prompt(&prompt_path).await;

// Manually serve a callback to trigger the error path
Expand Down
33 changes: 21 additions & 12 deletions server/src/service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@ impl Service {
} else {
#[cfg(any(test, feature = "test-util"))]
{
// For p2p test connections, use a dummy sender since p2p connections
// don't have a bus to assign unique names
// For p2p test connections, use a dummy sender since p2p
// connections don't have a bus to assign unique
// names
UniqueName::try_from(":p2p.test").unwrap()
}
#[cfg(not(any(test, feature = "test-util")))]
Expand Down Expand Up @@ -273,15 +274,17 @@ impl Service {
// The prompter will handle secret validation
// Here we just perform the unlock operation

// First, check for pending migrations (without holding collections lock)
// First, check for pending migrations (without holding
// collections lock)
for object in &not_unlocked {
let collection = {
let collections = service.collections.lock().await;
collections.get(object).cloned()
};

if let Some(collection) = collection {
// Check if this collection has a pending migration by name
// Check if this collection has a pending migration by
// name
let migration_opt = {
let pending = service.pending_migrations.lock().await;
pending.get(collection.name()).cloned()
Expand All @@ -294,7 +297,8 @@ impl Service {
migration_name
);

// Attempt migration with the provided secret (no locks held)
// Attempt migration with the provided secret (no
// locks held)
match migration.migrate(&service.data_dir, secret.as_ref()).await {
Ok(unlocked_keyring) => {
tracing::info!(
Expand Down Expand Up @@ -421,7 +425,8 @@ impl Service {
match item.get_secret(session.clone()).await {
Ok((secret,)) => {
secrets.insert(item.path().clone().into(), secret);
// To avoid iterating through all the remaining collections, if the
// To avoid iterating through all the remaining
// collections, if the
// items secrets are already retrieved.
if secrets.len() == items.len() {
break 'outer;
Expand Down Expand Up @@ -884,8 +889,8 @@ impl Service {
}
}

// Migration failed or no secret - create locked placeholder and register for
// pending migration
// Migration failed or no secret - create locked placeholder and
// register for pending migration
tracing::debug!(
"Creating locked placeholder for KWallet keyring '{name}', will migrate on unlock",
);
Expand Down Expand Up @@ -1223,9 +1228,11 @@ impl Service {
break;
} else if let Some(item) = collection.item_from_path(&resolved).await {
found = true;
// If collection is locked, can't perform any item lock/unlock operations
// If collection is locked, can't perform any item
// lock/unlock operations
if collection_locked {
// Unlocking an item when collection is locked requires unlocking collection
// Unlocking an item when collection is locked requires
// unlocking collection
if !locked {
with_prompt.push(resolved.clone());
} else {
Expand Down Expand Up @@ -1421,7 +1428,8 @@ impl Service {
let signal_emitter = self.signal_emitter(service_path)?;
Service::collection_created(&signal_emitter, &collection_path).await?;

// Emit PropertiesChanged for Collections property to invalidate client cache
// Emit PropertiesChanged for Collections property to invalidate client
// cache
self.collections_changed(&signal_emitter).await?;

tracing::info!(
Expand Down Expand Up @@ -1538,7 +1546,8 @@ impl Service {
let label = migration.label();
let alias = migration.alias();

// Create a collection for this migrated keyring with unique label and alias
// Create a collection for this migrated keyring with unique
// label and alias
let (unique_label, unique_alias) = {
let collections = self.collections.lock().await;
Self::make_unique_label_and_alias(&collections, label, alias)
Expand Down
8 changes: 4 additions & 4 deletions server/src/service/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,8 +720,8 @@ async fn lock_item_in_unlocked_collection() -> Result<(), Box<dyn std::error::Er
"Collection should be unlocked"
);

// When collection is unlocked, locking an item should happen directly without a
// prompt
// When collection is unlocked, locking an item should happen directly
// without a prompt
let locked = setup.service_api.lock(&[item.inner().path()], None).await?;

assert_eq!(locked.len(), 1, "Should have locked 1 item");
Expand Down Expand Up @@ -1064,8 +1064,8 @@ async fn create_collection_dismissed_plasma() -> Result<(), Box<dyn std::error::
async fn complete_collection_creation_no_pending() -> Result<(), Box<dyn std::error::Error>> {
let setup = TestServiceSetup::plain_session(true).await?;

// Try to complete collection creation with a prompt path that has no pending
// collection
// Try to complete collection creation with a prompt path that has no
// pending collection
let fake_prompt_path = ObjectPath::try_from("/org/freedesktop/secrets/prompt/p999").unwrap();
let secret = Secret::from("test-password-long-enough");

Expand Down
Loading
Loading