From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- third_party/rust/authenticator/src/manager.rs | 218 ++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 third_party/rust/authenticator/src/manager.rs (limited to 'third_party/rust/authenticator/src/manager.rs') diff --git a/third_party/rust/authenticator/src/manager.rs b/third_party/rust/authenticator/src/manager.rs new file mode 100644 index 0000000000..47e3a06c10 --- /dev/null +++ b/third_party/rust/authenticator/src/manager.rs @@ -0,0 +1,218 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use crate::authenticatorservice::AuthenticatorTransport; +use crate::authenticatorservice::{RegisterArgs, SignArgs}; +use crate::errors::*; +use crate::statecallback::StateCallback; +use crate::statemachine::StateMachine; +use crate::Pin; +use runloop::RunLoop; +use std::io; +use std::sync::mpsc::{channel, RecvTimeoutError, Sender}; +use std::time::Duration; + +enum QueueAction { + Register { + timeout: u64, + register_args: RegisterArgs, + status: Sender, + callback: StateCallback>, + }, + Sign { + timeout: u64, + sign_args: SignArgs, + status: Sender, + callback: StateCallback>, + }, + Cancel, + Reset { + timeout: u64, + status: Sender, + callback: StateCallback>, + }, + SetPin { + timeout: u64, + new_pin: Pin, + status: Sender, + callback: StateCallback>, + }, + InteractiveManagement { + timeout: u64, + status: Sender, + callback: StateCallback>, + }, +} + +pub struct Manager { + queue: RunLoop, + tx: Sender, +} + +impl Manager { + pub fn new() -> io::Result { + let (tx, rx) = channel(); + + // Start a new work queue thread. + let queue = RunLoop::new(move |alive| { + let mut sm = StateMachine::new(); + + while alive() { + match rx.recv_timeout(Duration::from_millis(50)) { + Ok(QueueAction::Register { + timeout, + register_args, + status, + callback, + }) => { + // This must not block, otherwise we can't cancel. + sm.register(timeout, register_args, status, callback); + } + + Ok(QueueAction::Sign { + timeout, + sign_args, + status, + callback, + }) => { + // This must not block, otherwise we can't cancel. + sm.sign(timeout, sign_args, status, callback); + } + + Ok(QueueAction::Cancel) => { + // Cancelling must block so that we don't start a new + // polling thread before the old one has shut down. + sm.cancel(); + } + + Ok(QueueAction::Reset { + timeout, + status, + callback, + }) => { + // Reset the token: Delete all keypairs, reset PIN + sm.reset(timeout, status, callback); + } + + Ok(QueueAction::SetPin { + timeout, + new_pin, + status, + callback, + }) => { + // This must not block, otherwise we can't cancel. + sm.set_pin(timeout, new_pin, status, callback); + } + + Ok(QueueAction::InteractiveManagement { + timeout, + status, + callback, + }) => { + // Manage token interactively + sm.manage(timeout, status, callback); + } + + Err(RecvTimeoutError::Disconnected) => { + break; + } + + _ => { /* continue */ } + } + } + + // Cancel any ongoing activity. + sm.cancel(); + })?; + + Ok(Self { queue, tx }) + } +} + +impl Drop for Manager { + fn drop(&mut self) { + self.queue.cancel(); + } +} + +impl AuthenticatorTransport for Manager { + fn register( + &mut self, + timeout: u64, + register_args: RegisterArgs, + status: Sender, + callback: StateCallback>, + ) -> Result<(), AuthenticatorError> { + let action = QueueAction::Register { + timeout, + register_args, + status, + callback, + }; + Ok(self.tx.send(action)?) + } + + fn sign( + &mut self, + timeout: u64, + sign_args: SignArgs, + status: Sender, + callback: StateCallback>, + ) -> crate::Result<()> { + let action = QueueAction::Sign { + timeout, + sign_args, + status, + callback, + }; + + self.tx.send(action)?; + Ok(()) + } + + fn cancel(&mut self) -> Result<(), AuthenticatorError> { + Ok(self.tx.send(QueueAction::Cancel)?) + } + + fn reset( + &mut self, + timeout: u64, + status: Sender, + callback: StateCallback>, + ) -> Result<(), AuthenticatorError> { + Ok(self.tx.send(QueueAction::Reset { + timeout, + status, + callback, + })?) + } + + fn set_pin( + &mut self, + timeout: u64, + new_pin: Pin, + status: Sender, + callback: StateCallback>, + ) -> crate::Result<()> { + Ok(self.tx.send(QueueAction::SetPin { + timeout, + new_pin, + status, + callback, + })?) + } + + fn manage( + &mut self, + timeout: u64, + status: Sender, + callback: StateCallback>, + ) -> Result<(), AuthenticatorError> { + Ok(self.tx.send(QueueAction::InteractiveManagement { + timeout, + status, + callback, + })?) + } +} -- cgit v1.2.3