Skip to content

Commit

Permalink
server: Add GetSecret, GetSecrets and SetSecret implementation
Browse files Browse the repository at this point in the history
Signed-off-by: Dhanuka Warusadura <dhanuka@gnome.org>
  • Loading branch information
warusadura authored and bilelmoussaoui committed Nov 18, 2024
1 parent f097dc5 commit de29404
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 11 deletions.
12 changes: 12 additions & 0 deletions server/src/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,18 @@ impl Collection {
items
}

pub async fn item_from_path(&self, path: &OwnedObjectPath) -> Option<item::Item> {
let items = self.items.lock().await;

for item in items.iter() {
if item.path() == path {
return Some(item.clone());
}
}

None
}

pub async fn dispatch_items(&self) -> Result<(), Error> {
let keyring_items = self.keyring.items().await;
let mut items = self.items.lock().await;
Expand Down
79 changes: 73 additions & 6 deletions server/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub struct Item {
locked: Arc<AtomicBool>,
inner: Arc<Mutex<oo7::portal::Item>>,
// Other attributes
_manager: Arc<Mutex<ServiceManager>>,
manager: Arc<Mutex<ServiceManager>>,
path: OwnedObjectPath,
}

Expand All @@ -32,12 +32,79 @@ impl Item {
}

#[zbus(out_args("secret"))]
pub async fn get_secret(&self, _session: ObjectPath<'_>) -> Result<SecretInner, ServiceError> {
todo!()
pub async fn get_secret(
&self,
session: OwnedObjectPath,
) -> Result<(SecretInner,), ServiceError> {
let manager = self.manager.lock().await;

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

if self.is_locked().await {
tracing::error!("Cannot get secret of a locked object `{}`", self.path);
return Err(ServiceError::IsLocked(format!(
"Cannot get secret of a locked object `{}`.",
self.path
)));
}

let inner = self.inner.lock().await;
let secret = inner.secret();

tracing::debug!("Secret retrieved from the item: {}.", self.path);

match session.aes_key() {
Some(key) => {
let iv = oo7::crypto::generate_iv();
let encrypted = oo7::crypto::encrypt(secret, &key, &iv);

Ok((SecretInner(
session.path().clone(),
iv,
encrypted,
"text/plain".to_owned(),
),))
}
None => Ok((SecretInner(
session.path().clone(),
Vec::new(),
secret.to_vec(),
"text/plain".to_owned(),
),)),
}
}

pub async fn set_secret(&self, _secret: SecretInner) -> Result<(), ServiceError> {
todo!()
pub async fn set_secret(&self, secret: SecretInner) -> Result<(), ServiceError> {
let SecretInner(session, iv, secret, _content_type) = secret;
let manager = self.manager.lock().await;

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

let mut inner = self.inner.lock().await;

match session.aes_key() {
Some(key) => {
let decrypted = oo7::crypto::decrypt(secret, &key, &iv);
inner.set_secret(decrypted);
}
None => {
inner.set_secret(secret);
}
}

Ok(())
}

#[zbus(property, name = "Locked")]
Expand Down Expand Up @@ -94,7 +161,7 @@ impl Item {
locked: Arc::new(AtomicBool::new(locked)),
inner: Arc::new(Mutex::new(item)),
path: OwnedObjectPath::try_from(format!("{}/{}", collection_path, item_index)).unwrap(),
_manager: manager,
manager,
}
}

Expand Down
33 changes: 30 additions & 3 deletions server/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,37 @@ impl Service {
#[zbus(out_args("secrets"))]
pub async fn get_secrets(
&self,
_items: Vec<OwnedObjectPath>,
_session: ObjectPath<'_>,
items: Vec<OwnedObjectPath>,
session: OwnedObjectPath,
) -> Result<HashMap<OwnedObjectPath, SecretInner>, ServiceError> {
todo!()
let mut secrets = HashMap::new();
let collections = self.collections.lock().await;

'outer: for collection in collections.iter() {
for item in &items {
if let Some(item) = collection.item_from_path(item).await {
match item.get_secret(session.clone()).await {
Ok((secret,)) => {
secrets.insert(item.path().clone(), secret);
// To avoid iterating through all the remaining collections, if the
// items secrets are already retrieved.
if secrets.len() == items.len() {
break 'outer;
}
}
// Avoid erroring out if an item is locked.
Err(ServiceError::IsLocked(_)) => {
continue;
}
Err(err) => {
return Err(err);
}
};
}
}
}

Ok(secrets)
}

#[zbus(out_args("collection"))]
Expand Down
4 changes: 4 additions & 0 deletions server/src/service_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ impl ServiceManager {
self.sessions.len()
}

pub fn session(&self, path: &OwnedObjectPath) -> Option<Arc<Session>> {
self.sessions.get(path).map(Arc::clone)
}

pub fn insert_session(&mut self, path: OwnedObjectPath, session: Arc<Session>) {
self.sessions.insert(path, session);
}
Expand Down
8 changes: 6 additions & 2 deletions server/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::service_manager::ServiceManager;

#[derive(Debug, Clone)]
pub struct Session {
_aes_key: Option<Arc<Key>>,
aes_key: Option<Arc<Key>>,
manager: Arc<Mutex<ServiceManager>>,
path: OwnedObjectPath,
}
Expand All @@ -34,12 +34,16 @@ impl Session {
Self {
path: OwnedObjectPath::try_from(format!("/org/freedesktop/secrets/session/s{index}"))
.unwrap(),
_aes_key: aes_key,
aes_key,
manager,
}
}

pub fn path(&self) -> &OwnedObjectPath {
&self.path
}

pub fn aes_key(&self) -> Option<Arc<Key>> {
self.aes_key.as_ref().map(Arc::clone)
}
}

0 comments on commit de29404

Please sign in to comment.