Skip to content

Commit deded30

Browse files
committed
Fix D-Bus deserialization for USB/Hybrid state
1 parent 6e36f94 commit deded30

4 files changed

Lines changed: 81 additions & 42 deletions

File tree

creds-lib/src/server.rs

Lines changed: 69 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
use std::collections::HashMap;
22

33
use serde::{Deserialize, Serialize};
4-
use zbus::{
5-
fdo,
6-
object_server::SignalEmitter,
7-
proxy,
8-
zvariant::{self, DeserializeDict, LE, Optional, OwnedValue, SerializeDict, Type, Value},
9-
};
4+
use zbus::zvariant::{self, DeserializeDict, LE, Optional, OwnedValue, SerializeDict, Type, Value};
105

116
use crate::model::{Operation, ViewUpdate};
127

@@ -225,9 +220,10 @@ impl TryFrom<Value<'_>> for Credential {
225220
*/
226221

227222
#[derive(SerializeDict, DeserializeDict, Type)]
223+
#[zvariant(signature = "a{sv}")]
228224
pub struct Device {
229-
id: String,
230-
transport: String,
225+
pub id: String,
226+
pub transport: String,
231227
}
232228

233229
impl TryFrom<Value<'_>> for Device {
@@ -330,13 +326,17 @@ impl From<crate::model::HybridState> for HybridState {
330326
match value {
331327
crate::model::HybridState::Idle => HybridState::Idle(OwnedValue::from(false)),
332328
crate::model::HybridState::Started(qr_code) => {
333-
HybridState::Idle(value_to_owned(Value::from(qr_code)))
329+
HybridState::Started(value_to_owned(&Value::from(qr_code)))
330+
}
331+
crate::model::HybridState::Connecting => {
332+
HybridState::Connecting(OwnedValue::from(false))
334333
}
335-
crate::model::HybridState::Connecting => HybridState::Idle(OwnedValue::from(false)),
336-
crate::model::HybridState::Connected => HybridState::Idle(OwnedValue::from(false)),
337-
crate::model::HybridState::Completed => HybridState::Idle(OwnedValue::from(false)),
338-
crate::model::HybridState::UserCancelled => HybridState::Idle(OwnedValue::from(false)),
339-
crate::model::HybridState::Failed => HybridState::Idle(OwnedValue::from(false)),
334+
crate::model::HybridState::Connected => HybridState::Connected(OwnedValue::from(false)),
335+
crate::model::HybridState::Completed => HybridState::Completed(OwnedValue::from(false)),
336+
crate::model::HybridState::UserCancelled => {
337+
HybridState::UserCancelled(OwnedValue::from(false))
338+
}
339+
crate::model::HybridState::Failed => HybridState::Failed(OwnedValue::from(false)),
340340
}
341341
}
342342
}
@@ -358,10 +358,28 @@ impl TryFrom<HybridState> for crate::model::HybridState {
358358
impl TryFrom<Value<'_>> for HybridState {
359359
type Error = zvariant::Error;
360360
fn try_from(value: Value<'_>) -> std::result::Result<Self, Self::Error> {
361-
let ctx = zvariant::serialized::Context::new_dbus(LE, 0);
362-
let encoded = zvariant::to_bytes(ctx, &value)?;
363-
let obj: Self = encoded.deserialize()?.0;
364-
Ok(obj)
361+
let fields: HashMap<String, Value<'_>> = value.try_into()?;
362+
let tag = fields
363+
.get("type")
364+
.ok_or(zvariant::Error::Message(
365+
"Expected a dictionary with `type` key".to_string(),
366+
))
367+
.and_then(|t| t.try_into())?;
368+
let value = fields.get("value").ok_or(zvariant::Error::Message(
369+
"Expected a dictionary with `value` key".to_string(),
370+
))?;
371+
match tag {
372+
"IDLE" => Ok(Self::Idle(value_to_owned(value))),
373+
"STARTED" => Ok(Self::Started(value_to_owned(value))),
374+
"CONNECTING" => Ok(Self::Connecting(value_to_owned(value))),
375+
"CONNECTED" => Ok(Self::Connected(value_to_owned(value))),
376+
"COMPLETED" => Ok(Self::Completed(value_to_owned(value))),
377+
"USER_CANCELLED" => Ok(Self::Completed(value_to_owned(value))),
378+
"FAILED" => Ok(Self::Failed(value_to_owned(value))),
379+
_ => Err(zvariant::Error::Message(format!(
380+
"Invalid HybridState type passed: {tag}"
381+
))),
382+
}
365383
}
366384
}
367385

@@ -370,31 +388,31 @@ impl From<HybridState> for Value<'_> {
370388
let mut fields = HashMap::new();
371389
match value {
372390
HybridState::Idle(owned_value) => {
373-
fields.insert("type", value_to_owned(Value::from("IDLE")));
391+
fields.insert("type", value_to_owned(&Value::from("IDLE")));
374392
fields.insert("value", owned_value);
375393
}
376394
HybridState::Started(owned_value) => {
377-
fields.insert("type", value_to_owned(Value::from("STARTED")));
395+
fields.insert("type", value_to_owned(&Value::from("STARTED")));
378396
fields.insert("value", owned_value);
379397
}
380398
HybridState::Connecting(owned_value) => {
381-
fields.insert("type", value_to_owned(Value::from("CONNECTING")));
399+
fields.insert("type", value_to_owned(&Value::from("CONNECTING")));
382400
fields.insert("value", owned_value);
383401
}
384402
HybridState::Connected(owned_value) => {
385-
fields.insert("type", value_to_owned(Value::from("CONNECTED")));
403+
fields.insert("type", value_to_owned(&Value::from("CONNECTED")));
386404
fields.insert("value", owned_value);
387405
}
388406
HybridState::Completed(owned_value) => {
389-
fields.insert("type", value_to_owned(Value::from("COMPLETED")));
407+
fields.insert("type", value_to_owned(&Value::from("COMPLETED")));
390408
fields.insert("value", owned_value);
391409
}
392410
HybridState::UserCancelled(owned_value) => {
393-
fields.insert("type", value_to_owned(Value::from("USER_CANCELLED")));
411+
fields.insert("type", value_to_owned(&Value::from("USER_CANCELLED")));
394412
fields.insert("value", owned_value);
395413
}
396414
HybridState::Failed(owned_value) => {
397-
fields.insert("type", value_to_owned(Value::from("FAILED")));
415+
fields.insert("type", value_to_owned(&Value::from("FAILED")));
398416
fields.insert("value", owned_value);
399417
}
400418
}
@@ -561,10 +579,31 @@ impl From<crate::model::UsbState> for UsbState {
561579
impl TryFrom<Value<'_>> for UsbState {
562580
type Error = zvariant::Error;
563581
fn try_from(value: Value<'_>) -> std::result::Result<Self, Self::Error> {
564-
let ctx = zvariant::serialized::Context::new_dbus(LE, 0);
565-
let encoded = zvariant::to_bytes(ctx, &value)?;
566-
let obj: Self = encoded.deserialize()?.0;
567-
Ok(obj)
582+
let fields: HashMap<String, Value<'_>> = value.try_into()?;
583+
let tag = fields
584+
.get("type")
585+
.ok_or(zvariant::Error::Message(
586+
"Expected a dictionary with `type` key".to_string(),
587+
))
588+
.and_then(|t| t.try_into())?;
589+
let value = fields.get("value").ok_or(zvariant::Error::Message(
590+
"Expected a dictionary with `value` key".to_string(),
591+
))?;
592+
match tag {
593+
"IDLE" => Ok(Self::Idle(value_to_owned(value))),
594+
"WAITING" => Ok(Self::Waiting(value_to_owned(value))),
595+
"SELECTING_DEVICE" => Ok(Self::SelectingDevice(value_to_owned(value))),
596+
"CONNECTED" => Ok(Self::SelectingDevice(value_to_owned(value))),
597+
"NEEDS_PIN" => Ok(Self::NeedsPin(value_to_owned(value))),
598+
"NEEDS_USER_VERIFICATION" => Ok(Self::NeedsUserVerification(value_to_owned(value))),
599+
"NEEDS_USER_PRESENCE" => Ok(Self::NeedsUserPresence(value_to_owned(value))),
600+
"SELECT_CREDENTIAL" => Ok(Self::SelectCredential(value_to_owned(value))),
601+
"COMPLETED" => Ok(Self::Completed(value_to_owned(value))),
602+
"FAILED" => Ok(Self::Failed(value_to_owned(value))),
603+
_ => Err(zvariant::Error::Message(format!(
604+
"Invalid UsbState type passed: {tag}"
605+
))),
606+
}
568607
}
569608
}
570609

@@ -672,7 +711,7 @@ pub struct ViewRequest {
672711
pub operation: Operation,
673712
}
674713

675-
fn value_to_owned(value: Value<'_>) -> OwnedValue {
714+
fn value_to_owned(value: &Value<'_>) -> OwnedValue {
676715
value
677716
.try_to_owned()
678717
.expect("non-file descriptor values to succeed")

creds-ui/src/client.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ impl CredentialServiceClient for DbusCredentialClient {
2929
.await?
3030
.get_available_public_key_devices()
3131
.await
32-
.map_err(|_| ())?;
32+
.map_err(|err| {
33+
tracing::error!("Failed to retrieve available devices/transports: {err}")
34+
})?;
3335
dbus_devices.into_iter().map(|d| d.try_into()).collect()
3436
}
3537

credsd/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ serde_json = "1.0.140"
1717
# serde_cbor = "0.11.1"
1818
tracing = "0.1.41"
1919
tracing-subscriber = "0.3"
20-
zbus = { version = "5.5.0", default-features = false, features = ["blocking-api", "tokio"] }
20+
zbus = { version = "5.9.0", default-features = false, features = ["tokio"] }
2121
libwebauthn = "~0.2.2"
2222
async-trait = "0.1.88"
2323
tokio = { version = "1.45.0", features = ["rt-multi-thread"] }

credsd/src/dbus/flow_control.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,10 @@ where
118118
.await
119119
.get_available_public_key_devices()
120120
.await
121-
.map_err(|_| {
122-
fdo::Error::Failed("Failed to get retrieve available devices".to_string())
123-
})?;
124-
Ok(devices.into_iter().map(Device::from).collect())
121+
.map_err(|_| fdo::Error::Failed("Failed to retrieve available devices".to_string()))?;
122+
let dbus_devices: Vec<Device> = devices.into_iter().map(Device::from).collect();
123+
124+
Ok(dbus_devices)
125125
}
126126

127127
async fn get_hybrid_credential(
@@ -133,9 +133,8 @@ where
133133
let signal_state = self.signal_state.clone();
134134
let object_server = object_server.clone();
135135
let task = tokio::spawn(async move {
136-
let interface: zbus::Result<InterfaceRef<InternalService<H, U, UC>>> = object_server
137-
.interface("/xyz/iinuwa/credentials/CredentialManagerInternal")
138-
.await;
136+
let interface: zbus::Result<InterfaceRef<FlowControlService<H, U, UC>>> =
137+
object_server.interface(SERVICE_PATH).await;
139138

140139
let emitter = match interface {
141140
Ok(ref i) => i.signal_emitter(),
@@ -185,9 +184,8 @@ where
185184
let signal_state = self.signal_state.clone();
186185
let object_server = object_server.clone();
187186
let task = tokio::spawn(async move {
188-
let interface: zbus::Result<InterfaceRef<InternalService<H, U, UC>>> = object_server
189-
.interface("/xyz/iinuwa/credentials/CredentialManagerInternal")
190-
.await;
187+
let interface: zbus::Result<InterfaceRef<FlowControlService<H, U, UC>>> =
188+
object_server.interface(SERVICE_PATH).await;
191189

192190
let emitter = match interface {
193191
Ok(ref i) => i.signal_emitter(),

0 commit comments

Comments
 (0)