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
215 changes: 72 additions & 143 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ endi.workspace = true
futures-lite = { workspace = true, optional = true }
futures-util.workspace = true
getrandom = "0.4"
hex = "0.4"
hkdf = { workspace = true, optional = true }
md-5 = { workspace = true, optional = true }
num.workspace = true
Expand Down
74 changes: 74 additions & 0 deletions client/fixtures/plain.keyring
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
[keyring]
display-name=Login
ctime=0
mtime=1441960049
lock-on-idle=false
lock-after=false

[917]
item-type=0
display-name=Remmina: Shore - password
secret=some password
mtime=1768377640
ctime=1768377640

[917:attribute0]
name=filename
type=string
value=/home/user/.local/share/remmina/group_rdp_shore_shore-sym.remmina

[917:attribute1]
name=key
type=string
value=password

[917:attribute2]
name=xdg:schema
type=string
value=org.remmina.Password

[918]
item-type=2
display-name=Binary
binary-secret=ff00ab
mtime=1198027852
ctime=1198027852

[918:attribute0]
name=num
type=uint32
value=3

[918:attribute1]
name=empty
type=string
value=

[918:attribute2]
name=escaped
type=string
value=\sa\tb\\c\n

[918:attribute3]
name=bad-number
type=uint32
value=not-a-number

[918:attribute4]
name=missing-number
type=uint32

[918:attribute5]
name=bad-escape
type=string
value=\q

[918:acl0]
display-name=some-app
path=/usr/bin/some-app
read-access=true
write-access=true
remove-access=true

[919]
item-type=0
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Legacy GNOME Keyring file format low level API.
//! Encrypted binary keyring format.

use std::{
collections::HashMap,
Expand All @@ -8,15 +8,12 @@ use std::{
use endi::{Endian, ReadBytes};
use zeroize::{Zeroize, ZeroizeOnDrop};

use super::{Secret, UnlockedItem};
use super::{FILE_HEADER, FILE_HEADER_LEN};
use crate::{
AsAttributes, crypto,
file::{Error, WeakKeyError},
AsAttributes, Secret, crypto,
file::{Error, UnlockedItem, WeakKeyError},
};

const FILE_HEADER: &[u8] = b"GnomeKeyring\n\r\0\n";
const FILE_HEADER_LEN: usize = FILE_HEADER.len();

pub const MAJOR_VERSION: u8 = 0;
pub const MINOR_VERSION: u8 = 0;

Expand Down
49 changes: 49 additions & 0 deletions client/src/file/api/legacy_keyring/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//! Legacy GNOME Keyring file format low level API.
//!
//! gnome-keyring stores a keyring either in an encrypted binary format, or as a
//! plain-text key file when the keyring password is empty.

mod encrypted;
mod plain;

pub use encrypted::MAJOR_VERSION;

use crate::{
Secret,
file::{Error, UnlockedItem},
};

const FILE_HEADER: &[u8] = b"GnomeKeyring\n\r\0\n";
const FILE_HEADER_LEN: usize = FILE_HEADER.len();

#[derive(Debug)]
pub enum Keyring {
Encrypted(encrypted::Keyring),
Plain(plain::Keyring),
}

impl Keyring {
/// Retrieve the keyring items.
///
/// The secret is ignored for plain keyrings.
pub fn decrypt_items(self, secret: &Secret) -> Result<Vec<UnlockedItem>, Error> {
match self {
Self::Encrypted(keyring) => keyring.decrypt_items(secret),
Self::Plain(keyring) => Ok(keyring.into_items()),
}
}
}

impl TryFrom<&[u8]> for Keyring {
type Error = Error;

fn try_from(value: &[u8]) -> Result<Self, Error> {
// Same as gnome-keyring, anything without the binary header is
// attempted as a plain keyring.
if value.starts_with(FILE_HEADER) {
encrypted::Keyring::try_from(value).map(Self::Encrypted)
} else {
plain::Keyring::try_from(value).map(Self::Plain)
}
}
}
Loading
Loading