use super::Pin; use crate::{ ctap2::{ commands::{ authenticator_config::{AuthConfigCommand, AuthConfigResult}, bio_enrollment::BioTemplateId, get_info::AuthenticatorInfo, PinUvAuthResult, }, server::{PublicKeyCredentialDescriptor, PublicKeyCredentialUserEntity}, }, BioEnrollmentResult, CredentialManagementResult, }; use serde::{Deserialize, Serialize as DeriveSer, Serializer}; use std::sync::mpsc::Sender; #[derive(Debug, Deserialize, DeriveSer)] pub enum CredManagementCmd { GetCredentials, DeleteCredential(PublicKeyCredentialDescriptor), UpdateUserInformation(PublicKeyCredentialDescriptor, PublicKeyCredentialUserEntity), } #[derive(Debug, Deserialize, DeriveSer)] pub enum BioEnrollmentCmd { GetFingerprintSensorInfo, GetEnrollments, StartNewEnrollment(Option), DeleteEnrollment(BioTemplateId), ChangeName(BioTemplateId, String), } #[derive(Debug)] pub enum InteractiveRequest { Quit, Reset, ChangePIN(Pin, Pin), SetPIN(Pin), ChangeConfig(AuthConfigCommand, Option), CredentialManagement(CredManagementCmd, Option), BioEnrollment(BioEnrollmentCmd, Option), } // Simply ignoring the Sender when serializing pub(crate) fn serialize_pin_required(_: &Sender, s: S) -> Result where S: Serializer, { s.serialize_none() } // Simply ignoring the Sender when serializing pub(crate) fn serialize_pin_invalid( _: &Sender, retries: &Option, s: S, ) -> Result where S: Serializer, { if let Some(r) = retries { s.serialize_u8(*r) } else { s.serialize_none() } } #[derive(Debug, DeriveSer)] pub enum StatusPinUv { #[serde(serialize_with = "serialize_pin_required")] PinRequired(Sender), #[serde(serialize_with = "serialize_pin_invalid")] InvalidPin(Sender, Option), PinIsTooShort, PinIsTooLong(usize), InvalidUv(Option), // This SHOULD ever only happen for CTAP2.0 devices that // use internal UV (e.g. fingerprint sensors) and failed (e.g. wrong // finger used). // PinAuthInvalid, // Folded into InvalidUv PinAuthBlocked, PinBlocked, PinNotSet, UvBlocked, } #[derive(Debug)] pub enum InteractiveUpdate { StartManagement((Sender, Option)), // We provide the already determined PUAT to be able to issue more requests without // forcing the user to enter another PIN. BioEnrollmentUpdate((BioEnrollmentResult, Option)), CredentialManagementUpdate((CredentialManagementResult, Option)), AuthConfigUpdate((AuthConfigResult, Option)), } #[derive(Debug)] pub enum StatusUpdate { /// We're waiting for the user to touch their token PresenceRequired, /// Sent if a PIN is needed (or was wrong), or some other kind of PIN-related /// error occurred. The Sender is for sending back a PIN (if needed). PinUvError(StatusPinUv), /// Sent, if multiple devices are found and the user has to select one SelectDeviceNotice, /// Sent when a token was selected for interactive management InteractiveManagement(InteractiveUpdate), /// Sent when a token returns multiple results for a getAssertion request SelectResultNotice(Sender>, Vec), } pub(crate) fn send_status(status: &Sender, msg: StatusUpdate) { match status.send(msg) { Ok(_) => {} Err(e) => error!("Couldn't send status: {:?}", e), }; }