diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client.rs | 33 | ||||
-rw-r--r-- | src/client/certificate.rs | 41 |
2 files changed, 51 insertions, 23 deletions
diff --git a/src/client.rs b/src/client.rs index 24ec550..ec9cc46 100644 --- a/src/client.rs +++ b/src/client.rs @@ -28,8 +28,8 @@ use crate::{ }; use self::certificate::{ - load_known_hosts_store_from_config, CertVerificationInfo, CertVerificationStatus, - CertVerifierAction, CertificateInteractionEvent, CertificateUpdateEvent, + load_known_hosts_store_from_config, CertConnectionAbortEvent, CertInteractionEvent, + CertTrustUpdateEvent, CertVerificationInfo, CertVerificationStatus, CertVerifierAction, CertificateVerificationMode, SkipServerVerification, TofuServerVerification, }; @@ -98,12 +98,16 @@ enum ClientState { pub(crate) enum InternalAsyncMessage { Connected, LostConnection, - CertificateActionRequest { + CertificateInteractionRequest { status: CertVerificationStatus, info: CertVerificationInfo, action_sender: oneshot::Sender<CertVerifierAction>, }, - TrustedCertificateUpdate(CertVerificationInfo), + CertificateTrustUpdate(CertVerificationInfo), + CertificateConnectionAbort { + status: CertVerificationStatus, + cert_info: CertVerificationInfo, + }, } #[derive(Debug, Clone)] @@ -386,8 +390,9 @@ fn update_sync_client( mut client: ResMut<Client>, mut connection_events: EventWriter<ConnectionEvent>, mut connection_lost_events: EventWriter<ConnectionLostEvent>, - mut certificate_interaction_events: EventWriter<CertificateInteractionEvent>, - mut certificate_update_events: EventWriter<CertificateUpdateEvent>, + mut certificate_interaction_events: EventWriter<CertInteractionEvent>, + mut cert_trust_update_events: EventWriter<CertTrustUpdateEvent>, + mut cert_connection_abort_events: EventWriter<CertConnectionAbortEvent>, ) { while let Ok(message) = client.internal_receiver.try_recv() { match message { @@ -399,19 +404,22 @@ fn update_sync_client( client.state = ClientState::Disconnected; connection_lost_events.send(ConnectionLostEvent); } - InternalAsyncMessage::CertificateActionRequest { + InternalAsyncMessage::CertificateInteractionRequest { status, info, action_sender, } => { - certificate_interaction_events.send(CertificateInteractionEvent { + certificate_interaction_events.send(CertInteractionEvent { status, info, action_sender: Mutex::new(Some(action_sender)), }); } - InternalAsyncMessage::TrustedCertificateUpdate(info) => { - certificate_update_events.send(CertificateUpdateEvent(info)); + InternalAsyncMessage::CertificateTrustUpdate(info) => { + cert_trust_update_events.send(CertTrustUpdateEvent(info)); + } + InternalAsyncMessage::CertificateConnectionAbort { status, cert_info } => { + cert_connection_abort_events.send(CertConnectionAbortEvent { status, cert_info }); } } } @@ -429,8 +437,9 @@ impl Plugin for QuinnetClientPlugin { fn build(&self, app: &mut App) { app.add_event::<ConnectionEvent>() .add_event::<ConnectionLostEvent>() - .add_event::<CertificateInteractionEvent>() - .add_event::<CertificateUpdateEvent>() + .add_event::<CertInteractionEvent>() + .add_event::<CertTrustUpdateEvent>() + .add_event::<CertConnectionAbortEvent>() // StartupStage::PreStartup so that resources created in commands are available to default startup_systems .add_startup_system_to_stage(StartupStage::PreStartup, start_async_client) .add_system(update_sync_client); diff --git a/src/client/certificate.rs b/src/client/certificate.rs index 33587da..94f2abe 100644 --- a/src/client/certificate.rs +++ b/src/client/certificate.rs @@ -21,7 +21,7 @@ pub const DEFAULT_CERT_VERIFIER_BEHAVIOUR: CertVerifierBehaviour = CertVerifierBehaviour::ImmediateAction(CertVerifierAction::AbortConnection); /// Event raised when a user/app interaction is needed for the server's certificate validation -pub struct CertificateInteractionEvent { +pub struct CertInteractionEvent { /// The current status of the verification pub status: CertVerificationStatus, /// Server & Certificate info @@ -30,7 +30,7 @@ pub struct CertificateInteractionEvent { pub(crate) action_sender: Mutex<Option<oneshot::Sender<CertVerifierAction>>>, } -impl CertificateInteractionEvent { +impl CertInteractionEvent { pub fn apply_cert_verifier_action( &self, action: CertVerifierAction, @@ -48,7 +48,13 @@ impl CertificateInteractionEvent { } /// Event raised when a new certificate is trusted -pub struct CertificateUpdateEvent(pub CertVerificationInfo); +pub struct CertTrustUpdateEvent(pub CertVerificationInfo); + +/// Event raised when a connection is aborted during the certificate verification +pub struct CertConnectionAbortEvent { + pub status: CertVerificationStatus, + pub cert_info: CertVerificationInfo, +} /// How the client should handle the server certificate. #[derive(Debug, Clone)] @@ -250,19 +256,19 @@ impl TofuServerVerification { .unwrap_or(&DEFAULT_CERT_VERIFIER_BEHAVIOUR); match behaviour { CertVerifierBehaviour::ImmediateAction(action) => { - self.apply_verifier_immediate_action(action, cert_info) + self.apply_verifier_immediate_action(action, status, cert_info) } CertVerifierBehaviour::RequestClientAction => { let (action_sender, cert_action_recv) = oneshot::channel::<CertVerifierAction>(); self.to_sync_client - .try_send(InternalAsyncMessage::CertificateActionRequest { - status, + .try_send(InternalAsyncMessage::CertificateInteractionRequest { + status: status.clone(), info: cert_info.clone(), action_sender, }) .unwrap(); match block_on(cert_action_recv) { - Ok(action) => self.apply_verifier_immediate_action(&action, cert_info), + Ok(action) => self.apply_verifier_immediate_action(&action, status, cert_info), Err(err) => Err(rustls::Error::InvalidCertificateData(format!( "Failed to receive CertVerifierAction: {}", err @@ -275,12 +281,25 @@ impl TofuServerVerification { fn apply_verifier_immediate_action( &self, action: &CertVerifierAction, + status: CertVerificationStatus, cert_info: CertVerificationInfo, ) -> Result<rustls::client::ServerCertVerified, rustls::Error> { match action { - CertVerifierAction::AbortConnection => Err(rustls::Error::InvalidCertificateData( - format!("CertVerifierAction requested to abort the connection"), - )), + CertVerifierAction::AbortConnection => { + match self.to_sync_client.try_send( + InternalAsyncMessage::CertificateConnectionAbort { + status: status, + cert_info, + }, + ) { + Ok(_) => Err(rustls::Error::InvalidCertificateData(format!( + "CertVerifierAction requested to abort the connection" + ))), + Err(_) => Err(rustls::Error::General(format!( + "Failed to signal CertificateConnectionAbort" + ))), + } + } CertVerifierAction::TrustOnce => Ok(rustls::client::ServerCertVerified::assertion()), CertVerifierAction::TrustAndStore => { // If we need to store them to a file @@ -298,7 +317,7 @@ impl TofuServerVerification { // In all cases raise an event containing the new certificate entry match self .to_sync_client - .try_send(InternalAsyncMessage::TrustedCertificateUpdate(cert_info)) + .try_send(InternalAsyncMessage::CertificateTrustUpdate(cert_info)) { Ok(_) => Ok(rustls::client::ServerCertVerified::assertion()), Err(_) => Err(rustls::Error::General(format!( |