22//! the credential request through the trusted UI.
33
44use std:: sync:: Mutex ;
5- use std:: { collections :: VecDeque , fmt:: Debug , sync:: Arc } ;
5+ use std:: { fmt:: Debug , sync:: Arc } ;
66
77use async_trait:: async_trait;
88use credentialsd_common:: model:: {
9- Device , Error as CredentialServiceError , Operation , PortalBackendOptions , RequestId ,
10- RequestingApplication , UserInteractedEvent , WebAuthnError ,
9+ Error as CredentialServiceError , Operation , PortalBackendOptions , RequestingApplication ,
10+ UserInteractedEvent , WebAuthnError ,
1111} ;
12- use credentialsd_common:: server:: { BackgroundEvent , ViewRequest , WindowHandle } ;
12+ use credentialsd_common:: server:: { BackgroundEvent , WindowHandle } ;
1313use futures_lite:: { Stream , StreamExt } ;
1414use tokio:: sync:: oneshot;
15- use tokio:: {
16- sync:: {
17- mpsc:: { self , Sender } ,
18- Mutex as AsyncMutex ,
19- } ,
20- task:: AbortHandle ,
21- } ;
22- use zbus:: {
23- connection:: { Builder , Connection } ,
24- fdo, interface,
25- object_server:: { InterfaceRef , SignalEmitter } ,
26- ObjectServer ,
15+ use tokio:: sync:: {
16+ mpsc:: { self , Sender } ,
17+ Mutex as AsyncMutex ,
2718} ;
19+ use zbus:: connection:: { Builder , Connection } ;
2820
2921use crate :: credential_service:: ManageDevice ;
3022use crate :: dbus:: ui_control:: Ceremony ;
3123use crate :: dbus:: UiControlServiceClient ;
3224use crate :: {
33- credential_service:: { hybrid :: HybridState , nfc :: NfcState , UsbState } ,
25+ credential_service:: UsbState ,
3426 dbus:: ui_control:: UiController ,
3527 model:: { CredentialRequest , CredentialResponse } ,
3628} ;
3729
38- pub const SERVICE_PATH : & str = "/xyz/iinuwa/credentialsd/FlowControl" ;
3930pub const SERVICE_NAME : & str = "xyz.iinuwa.credentialsd.FlowControl" ;
4031
4132pub async fn start_flow_control_service < M : ManageDevice + Debug + Send + Sync + ' static > (
@@ -51,22 +42,7 @@ pub async fn start_flow_control_service<M: ManageDevice + Debug + Send + Sync +
5142) > {
5243 let svc = Arc :: new ( AsyncMutex :: new ( device_manager) ) ;
5344 let svc2 = svc. clone ( ) ;
54- let conn = Builder :: session ( ) ?
55- . name ( SERVICE_NAME ) ?
56- . serve_at (
57- SERVICE_PATH ,
58- FlowControlDbusService {
59- signal_state : Arc :: new ( AsyncMutex :: new ( SignalState :: Idle ) ) ,
60- svc,
61- pin_tx : Arc :: new ( AsyncMutex :: new ( None ) ) ,
62- cred_tx : Arc :: new ( AsyncMutex :: new ( None ) ) ,
63- usb_event_forwarder_task : Arc :: new ( AsyncMutex :: new ( None ) ) ,
64- nfc_event_forwarder_task : Arc :: new ( AsyncMutex :: new ( None ) ) ,
65- hybrid_event_forwarder_task : Arc :: new ( AsyncMutex :: new ( None ) ) ,
66- } ,
67- ) ?
68- . build ( )
69- . await ?;
45+ let conn = Builder :: session ( ) ?. name ( SERVICE_NAME ) ?. build ( ) . await ?;
7046 let ( initiator_tx, mut initiator_rx) = mpsc:: channel :: < (
7147 CredentialRequest ,
7248 RequestingApplication ,
@@ -261,273 +237,6 @@ fn forward_background_event_stream(
261237 } ) ;
262238}
263239
264- struct FlowControlService < M : ManageDevice > {
265- svc : Arc < AsyncMutex < M > > ,
266- signal_state : Arc < AsyncMutex < SignalState > > ,
267- pin_tx : Arc < AsyncMutex < Option < Sender < String > > > > ,
268- cred_tx : Arc < AsyncMutex < Option < Sender < String > > > > ,
269- usb_event_forwarder_task : Arc < AsyncMutex < Option < AbortHandle > > > ,
270- nfc_event_forwarder_task : Arc < AsyncMutex < Option < AbortHandle > > > ,
271- hybrid_event_forwarder_task : Arc < AsyncMutex < Option < AbortHandle > > > ,
272- }
273-
274- impl < M : ManageDevice > FlowControlService < M > {
275- fn send_update ( & self ) { }
276- }
277-
278- struct FlowControlDbusService < M : ManageDevice > {
279- svc : Arc < AsyncMutex < M > > ,
280-
281- signal_state : Arc < AsyncMutex < SignalState > > ,
282-
283- cred_tx : Arc < AsyncMutex < Option < Sender < String > > > > ,
284- pin_tx : Arc < AsyncMutex < Option < Sender < String > > > > ,
285-
286- hybrid_event_forwarder_task : Arc < AsyncMutex < Option < AbortHandle > > > ,
287- nfc_event_forwarder_task : Arc < AsyncMutex < Option < AbortHandle > > > ,
288- usb_event_forwarder_task : Arc < AsyncMutex < Option < AbortHandle > > > ,
289- }
290-
291- /// The following methods are for communication between the [trusted]
292- /// UI and the credential service, and should not be called by arbitrary
293- /// clients.
294- #[ interface(
295- name = "xyz.iinuwa.credentialsd.FlowControl1" ,
296- proxy(
297- gen_blocking = false ,
298- default_path = "/xyz/iinuwa/credentialsd/FlowControl" ,
299- default_service = "xyz.iinuwa.credentialsd.FlowControl" ,
300- )
301- ) ]
302- impl < M > FlowControlDbusService < M >
303- where
304- M : ManageDevice + Debug + Send + Sync + ' static ,
305- {
306- async fn subscribe (
307- & self ,
308- #[ zbus( signal_emitter) ] emitter : SignalEmitter < ' _ > ,
309- ) -> fdo:: Result < ( ) > {
310- let mut signal_state = self . signal_state . lock ( ) . await ;
311- match * signal_state {
312- SignalState :: Idle => { }
313- SignalState :: Pending ( ref mut pending) => {
314- for msg in pending. iter_mut ( ) {
315- emitter. state_changed ( msg. clone ( ) ) . await ?;
316- }
317- }
318- SignalState :: Active => { }
319- } ;
320- * signal_state = SignalState :: Active ;
321- Ok ( ( ) )
322- }
323-
324- async fn get_available_public_key_devices ( & self ) -> fdo:: Result < Vec < Device > > {
325- let devices = self
326- . svc
327- . lock ( )
328- . await
329- . get_available_public_key_devices ( )
330- . await
331- . map_err ( |_| fdo:: Error :: Failed ( "Failed to retrieve available devices" . to_string ( ) ) ) ?;
332- let dbus_devices: Vec < Device > = devices. into_iter ( ) . map ( Device :: from) . collect ( ) ;
333-
334- Ok ( dbus_devices)
335- }
336-
337- async fn get_hybrid_credential (
338- & self ,
339- #[ zbus( object_server) ] object_server : & ObjectServer ,
340- ) -> fdo:: Result < ( ) > {
341- let svc = self . svc . lock ( ) . await ;
342- let mut stream = svc. get_hybrid_credential ( ) . await ;
343- let signal_state = self . signal_state . clone ( ) ;
344- let object_server = object_server. clone ( ) ;
345- let task = tokio:: spawn ( async move {
346- let interface: zbus:: Result < InterfaceRef < FlowControlDbusService < M > > > =
347- object_server. interface ( SERVICE_PATH ) . await ;
348-
349- let emitter = match interface {
350- Ok ( ref i) => i. signal_emitter ( ) ,
351- Err ( err) => {
352- tracing:: error!( "Failed to get connection to D-Bus to send signals: {err}" ) ;
353- return ;
354- }
355- } ;
356- while let Some ( state) = stream. next ( ) . await {
357- let event = ( & state) . into ( ) ;
358- if let Err ( err) = send_state_update ( emitter, & signal_state, event) . await {
359- tracing:: error!( "Failed to send state update to UI: {err}" ) ;
360- break ;
361- } ;
362- match state {
363- HybridState :: Completed | HybridState :: Failed => {
364- break ;
365- }
366- _ => { }
367- } ;
368- }
369- } )
370- . abort_handle ( ) ;
371- if let Some ( prev_task) = self . hybrid_event_forwarder_task . lock ( ) . await . replace ( task) {
372- prev_task. abort ( ) ;
373- }
374- Ok ( ( ) )
375- }
376-
377- async fn get_usb_credential (
378- & self ,
379- #[ zbus( object_server) ] object_server : & ObjectServer ,
380- ) -> fdo:: Result < ( ) > {
381- let mut stream = self . svc . lock ( ) . await . get_usb_credential ( ) . await ;
382- let usb_pin_tx = self . pin_tx . clone ( ) ;
383- let usb_cred_tx = self . cred_tx . clone ( ) ;
384- let signal_state = self . signal_state . clone ( ) ;
385- let object_server = object_server. clone ( ) ;
386- let task = tokio:: spawn ( async move {
387- let interface: zbus:: Result < InterfaceRef < FlowControlDbusService < M > > > =
388- object_server. interface ( SERVICE_PATH ) . await ;
389-
390- let emitter = match interface {
391- Ok ( ref i) => i. signal_emitter ( ) ,
392- Err ( err) => {
393- tracing:: error!( "Failed to get connection to D-Bus to send signals: {err}" ) ;
394- return ;
395- }
396- } ;
397- while let Some ( state) = stream. next ( ) . await {
398- let event = ( & state) . into ( ) ;
399- if let Err ( err) = send_state_update ( emitter, & signal_state, event) . await {
400- tracing:: error!( "Failed to send state update to UI: {err}" ) ;
401- break ;
402- } ;
403- match state {
404- UsbState :: NeedsPin { pin_tx, .. } => {
405- let mut usb_pin_tx = usb_pin_tx. lock ( ) . await ;
406- let _ = usb_pin_tx. insert ( pin_tx) ;
407- }
408- UsbState :: SelectingCredential { cred_tx, .. } => {
409- let mut usb_cred_tx = usb_cred_tx. lock ( ) . await ;
410- let _ = usb_cred_tx. insert ( cred_tx) ;
411- }
412- UsbState :: Completed | UsbState :: Failed ( _) => {
413- break ;
414- }
415- _ => { }
416- } ;
417- }
418- } )
419- . abort_handle ( ) ;
420- if let Some ( prev_task) = self . usb_event_forwarder_task . lock ( ) . await . replace ( task) {
421- prev_task. abort ( ) ;
422- }
423- Ok ( ( ) )
424- }
425-
426- async fn get_nfc_credential (
427- & self ,
428- #[ zbus( object_server) ] object_server : & ObjectServer ,
429- ) -> fdo:: Result < ( ) > {
430- let mut stream = self . svc . lock ( ) . await . get_nfc_credential ( ) . await ;
431- let nfc_pin_tx = self . pin_tx . clone ( ) ;
432- let nfc_cred_tx = self . cred_tx . clone ( ) ;
433- let signal_state = self . signal_state . clone ( ) ;
434- let object_server = object_server. clone ( ) ;
435- let task = tokio:: spawn ( async move {
436- let interface: zbus:: Result < InterfaceRef < FlowControlDbusService < M > > > =
437- object_server. interface ( SERVICE_PATH ) . await ;
438-
439- let emitter = match interface {
440- Ok ( ref i) => i. signal_emitter ( ) ,
441- Err ( err) => {
442- tracing:: error!( "Failed to get connection to D-Bus to send signals: {err}" ) ;
443- return ;
444- }
445- } ;
446- while let Some ( state) = stream. next ( ) . await {
447- let event = ( & state) . into ( ) ;
448- if let Err ( err) = send_state_update ( emitter, & signal_state, event) . await {
449- tracing:: error!( "Failed to send state update to UI: {err}" ) ;
450- break ;
451- } ;
452- match state {
453- NfcState :: NeedsPin { pin_tx, .. } => {
454- let mut nfc_pin_tx = nfc_pin_tx. lock ( ) . await ;
455- let _ = nfc_pin_tx. insert ( pin_tx) ;
456- }
457- NfcState :: SelectingCredential { cred_tx, .. } => {
458- let mut nfc_cred_tx = nfc_cred_tx. lock ( ) . await ;
459- let _ = nfc_cred_tx. insert ( cred_tx) ;
460- }
461- NfcState :: Completed | NfcState :: Failed ( _) => {
462- break ;
463- }
464- _ => { }
465- } ;
466- }
467- } )
468- . abort_handle ( ) ;
469- if let Some ( prev_task) = self . nfc_event_forwarder_task . lock ( ) . await . replace ( task) {
470- prev_task. abort ( ) ;
471- }
472- Ok ( ( ) )
473- }
474-
475- async fn enter_client_pin ( & self , pin : String ) -> fdo:: Result < ( ) > {
476- if let Some ( pin_tx) = self . pin_tx . lock ( ) . await . take ( ) {
477- pin_tx. send ( pin) . await . unwrap ( ) ;
478- }
479- Ok ( ( ) )
480- }
481-
482- async fn select_credential ( & self , credential_id : String ) -> fdo:: Result < ( ) > {
483- if let Some ( cred_tx) = self . cred_tx . lock ( ) . await . take ( ) {
484- cred_tx. send ( credential_id) . await . unwrap ( ) ;
485- }
486- Ok ( ( ) )
487- }
488-
489- async fn cancel_request ( & self , request_id : RequestId ) -> fdo:: Result < ( ) > {
490- self . svc . lock ( ) . await . cancel_request ( request_id) . await ;
491- Ok ( ( ) )
492- }
493-
494- #[ zbus( signal) ]
495- async fn state_changed (
496- emitter : & SignalEmitter < ' _ > ,
497- update : BackgroundEvent ,
498- ) -> zbus:: Result < ( ) > ;
499- }
500- async fn send_state_update (
501- emitter : & SignalEmitter < ' _ > ,
502- signal_state : & Arc < AsyncMutex < SignalState > > ,
503- update : BackgroundEvent ,
504- ) -> fdo:: Result < ( ) > {
505- let mut signal_state = signal_state. lock ( ) . await ;
506- match * signal_state {
507- SignalState :: Idle => {
508- let pending = VecDeque :: from ( [ update] ) ;
509- * signal_state = SignalState :: Pending ( pending) ;
510- }
511- SignalState :: Pending ( ref mut pending) => {
512- pending. push_back ( update) ;
513- }
514- SignalState :: Active => {
515- emitter. state_changed ( update) . await ?;
516- }
517- } ;
518- Ok ( ( ) )
519- }
520-
521- enum SignalState {
522- /// No state
523- Idle ,
524- /// Waiting for client to signal that it's ready to receive events.
525- /// Holds a cache of events to send once the client connects.
526- Pending ( VecDeque < BackgroundEvent > ) ,
527- /// Client is actively receiving messages.
528- Active ,
529- }
530-
531240/// Coordinates between user and various devices connected to the machine to
532241/// fulfill credential requests.
533242#[ async_trait]
0 commit comments