Skip to content

Commit 70a0b89

Browse files
committed
Add some error logs to USB handler
1 parent e3d64ba commit 70a0b89

2 files changed

Lines changed: 111 additions & 67 deletions

File tree

  • xyz-iinuwa-credential-manager-portal-gtk/src/credential_service

xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ enum AuthenticatorResponse {
197197
#[derive(Debug, Clone)]
198198
pub enum Error {
199199
AuthenticatorError,
200-
Unknown,
201200
}
202201

203202
impl From<MakeCredentialResponse> for AuthenticatorResponse {

xyz-iinuwa-credential-manager-portal-gtk/src/credential_service/usb.rs

Lines changed: 111 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,33 @@ impl InProcessUsbHandler {
3838
let (signal_tx, mut signal_rx) = mpsc::channel(256);
3939
let (cred_tx, mut cred_rx) = mpsc::channel(1);
4040
debug!("polling for USB status");
41+
let mut failures = 0;
4142
loop {
4243
tracing::debug!("current usb state: {:?}", state);
4344
let prev_usb_state = state;
4445
let next_usb_state = match prev_usb_state {
4546
UsbStateInternal::Idle | UsbStateInternal::Waiting => {
46-
let mut hid_devices =
47-
libwebauthn::transport::hid::list_devices().await.unwrap();
48-
if hid_devices.is_empty() {
49-
let state = UsbStateInternal::Waiting;
50-
Ok(state)
51-
} else if hid_devices.len() == 1 {
52-
Ok(UsbStateInternal::Connected(hid_devices.swap_remove(0)))
53-
} else {
54-
Ok(UsbStateInternal::SelectingDevice(hid_devices))
47+
match libwebauthn::transport::hid::list_devices().await {
48+
Ok(mut hid_devices) => {
49+
if hid_devices.is_empty() {
50+
let state = UsbStateInternal::Waiting;
51+
Ok(state)
52+
} else if hid_devices.len() == 1 {
53+
Ok(UsbStateInternal::Connected(hid_devices.swap_remove(0)))
54+
} else {
55+
Ok(UsbStateInternal::SelectingDevice(hid_devices))
56+
}
57+
}
58+
Err(err) => {
59+
failures += 1;
60+
if failures == 5 {
61+
Err(format!("Failed to list USB authenticators: {:?}. Cancelling USB state updates.", err))
62+
} else {
63+
tracing::warn!("Failed to list USB authenticators: {:?}. Throttling USB state updates", err);
64+
tokio::time::sleep(Duration::from_secs(1)).await;
65+
Ok(prev_usb_state)
66+
}
67+
}
5568
}
5669
}
5770
UsbStateInternal::SelectingDevice(hid_devices) => {
@@ -265,54 +278,79 @@ async fn handle_events(
265278
mut device: HidDevice,
266279
signal_tx: &Sender<Result<UsbUvMessage, String>>,
267280
) {
268-
let (mut channel, state_rx) = device.channel().await.unwrap();
269-
let signal_tx2 = signal_tx.clone().downgrade();
270-
tokio::spawn(async move {
271-
handle_usb_updates(&signal_tx2, state_rx).await;
272-
debug!("Reached end of USB update task");
273-
});
274-
match cred_request {
275-
CredentialRequest::CreatePublicKeyCredentialRequest(make_cred_request) => loop {
276-
match channel.webauthn_make_credential(make_cred_request).await {
277-
Ok(response) => {
278-
notify_ceremony_completed(
279-
signal_tx,
280-
AuthenticatorResponse::CredentialCreated(response),
281-
)
282-
.await;
283-
break;
284-
}
285-
Err(WebAuthnError::Ctap(ctap_error)) if ctap_error.is_retryable_user_error() => {
286-
warn!("Retrying WebAuthn make credential operation");
287-
continue;
288-
}
289-
Err(err) => {
290-
notify_ceremony_failed(signal_tx, err.to_string()).await;
291-
break;
292-
}
293-
};
294-
},
295-
CredentialRequest::GetPublicKeyCredentialRequest(get_cred_request) => loop {
296-
match channel.webauthn_get_assertion(get_cred_request).await {
297-
Ok(response) => {
298-
notify_ceremony_completed(
299-
signal_tx,
300-
AuthenticatorResponse::CredentialsAsserted(response),
301-
)
302-
.await;
303-
break;
304-
}
305-
Err(WebAuthnError::Ctap(ctap_error)) if ctap_error.is_retryable_user_error() => {
306-
warn!("Retrying WebAuthn get credential operation");
307-
continue;
308-
}
309-
Err(err) => {
310-
notify_ceremony_failed(signal_tx, err.to_string()).await;
311-
break;
312-
}
281+
let device_debug = device.to_string();
282+
match device.channel().await {
283+
Err(err) => {
284+
tracing::error!("Failed to open channel to USB authenticator, cannot receive user verification events: {:?}", err);
285+
}
286+
Ok((mut channel, state_rx)) => {
287+
let signal_tx2 = signal_tx.clone().downgrade();
288+
tokio::spawn(async move {
289+
handle_usb_updates(&signal_tx2, state_rx).await;
290+
debug!("Reached end of USB update task");
291+
});
292+
match cred_request {
293+
CredentialRequest::CreatePublicKeyCredentialRequest(make_cred_request) => loop {
294+
tracing::debug!(
295+
"Polling for credential from USB authenticator {}",
296+
&device_debug
297+
);
298+
match channel.webauthn_make_credential(make_cred_request).await {
299+
Ok(response) => {
300+
tracing::debug!("Received attestation from USB authenticator");
301+
notify_ceremony_completed(
302+
signal_tx,
303+
AuthenticatorResponse::CredentialCreated(response),
304+
)
305+
.await;
306+
break;
307+
}
308+
Err(WebAuthnError::Ctap(ctap_error))
309+
if ctap_error.is_retryable_user_error() =>
310+
{
311+
warn!("Retrying WebAuthn make credential operation");
312+
continue;
313+
}
314+
Err(err) => {
315+
tracing::warn!(
316+
"Failed to create credential with USB authenticator: {:?}",
317+
err
318+
);
319+
notify_ceremony_failed(signal_tx, err.to_string()).await;
320+
break;
321+
}
322+
};
323+
},
324+
CredentialRequest::GetPublicKeyCredentialRequest(get_cred_request) => loop {
325+
match channel.webauthn_get_assertion(get_cred_request).await {
326+
Ok(response) => {
327+
tracing::debug!("Received assertion from USB authenticator");
328+
notify_ceremony_completed(
329+
signal_tx,
330+
AuthenticatorResponse::CredentialsAsserted(response),
331+
)
332+
.await;
333+
break;
334+
}
335+
Err(WebAuthnError::Ctap(ctap_error))
336+
if ctap_error.is_retryable_user_error() =>
337+
{
338+
tracing::warn!("Retrying WebAuthn get credential operation");
339+
continue;
340+
}
341+
Err(err) => {
342+
tracing::warn!(
343+
"Failed to get credential from USB authenticator: {:?}",
344+
err
345+
);
346+
notify_ceremony_failed(signal_tx, err.to_string()).await;
347+
break;
348+
}
349+
};
350+
},
313351
};
314-
},
315-
};
352+
}
353+
}
316354
}
317355

318356
async fn notify_ceremony_completed(
@@ -326,7 +364,9 @@ async fn notify_ceremony_completed(
326364
}
327365

328366
async fn notify_ceremony_failed(signal_tx: &Sender<Result<UsbUvMessage, String>>, err: String) {
329-
signal_tx.send(Err(err)).await.unwrap();
367+
if let Err(tx_err) = signal_tx.send(Err(err)).await {
368+
tracing::error!("Failed to notify that ceremony failed: {:?}", tx_err);
369+
}
330370
}
331371

332372
impl UsbHandler for InProcessUsbHandler {
@@ -511,25 +551,31 @@ async fn handle_usb_updates(
511551
};
512552
match msg {
513553
UxUpdate::UvRetry { attempts_left } => {
514-
signal_tx
554+
if let Err(err) = signal_tx
515555
.send(Ok(UsbUvMessage::NeedsUserVerification { attempts_left }))
516556
.await
517-
.unwrap();
557+
{
558+
tracing::error!("Authenticator requested user verficiation, but we cannot relay the message to credential service: {:?}", err);
559+
}
518560
}
519561
UxUpdate::PinRequired(pin_update) => {
520562
if pin_update.attempts_left.is_some_and(|num| num <= 1) {
521563
// TODO: cancel authenticator operation
522-
signal_tx.send(Err("No more PIN attempts allowed. Select a different authenticator or try again later.".to_string())).await.unwrap();
564+
if let Err(err) = signal_tx.send(Err("No more PIN attempts allowed. Select a different authenticator or try again later.".to_string())).await {
565+
tracing::error!("Authenticator cannot process anymore PIN requests, but we cannot relay the message to credential service: {:?}", err);
566+
}
523567
continue;
524568
}
525569
let (pin_tx, mut pin_rx) = mpsc::channel(1);
526-
signal_tx
570+
if let Err(err) = signal_tx
527571
.send(Ok(UsbUvMessage::NeedsPin {
528572
pin_tx,
529573
attempts_left: pin_update.attempts_left,
530574
}))
531575
.await
532-
.unwrap();
576+
{
577+
tracing::error!("Authenticator requested a PIN from the user, but we cannot relay the message to the credential service: {:?}", err);
578+
}
533579
match pin_rx.recv().await {
534580
Some(pin) => match pin_update.send_pin(&pin) {
535581
Ok(()) => {}
@@ -539,10 +585,9 @@ async fn handle_usb_updates(
539585
}
540586
}
541587
UxUpdate::PresenceRequired => {
542-
signal_tx
543-
.send(Ok(UsbUvMessage::NeedsUserPresence))
544-
.await
545-
.unwrap();
588+
if let Err(err) = signal_tx.send(Ok(UsbUvMessage::NeedsUserPresence)).await {
589+
tracing::error!("Authenticator requested user presence, but we cannot relay the message to the credential service: {:?}", err);
590+
}
546591
}
547592
}
548593
}

0 commit comments

Comments
 (0)