From 055b03838da6fa6dd91744260cbee33168d53079 Mon Sep 17 00:00:00 2001 From: Artemy Egorov Date: Wed, 7 Aug 2024 13:40:24 +0300 Subject: [PATCH] fix: remove insecure gemini client, add secure file based cert verifier --- src-tauri/src/main.rs | 10 +++- .../process_input/insecure_gemini_client.rs | 54 ------------------- src-tauri/src/process_input/mod.rs | 7 ++- src-tauri/src/process_input/process_url.rs | 23 +++++--- src-tauri/src/types.rs | 7 ++- src-tauri/src/utils.rs | 9 ++++ 6 files changed, 43 insertions(+), 67 deletions(-) delete mode 100644 src-tauri/src/process_input/insecure_gemini_client.rs diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 85e88f7..451f9c9 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -9,7 +9,7 @@ mod utils; use tokio::sync::Mutex; use types::{VigiError, VigiJsState, VigiState}; -use utils::{read_or_create_jsonl, read_or_create_number}; +use utils::{create_file, read_or_create_jsonl, read_or_create_number}; #[tauri::command] async fn update_input( @@ -133,6 +133,14 @@ async fn setup( state.current_tab_index_path = local_data_dir.join("current_tab_index"); state.current_tab_index = read_or_create_number(&state.current_tab_index_path); + println!("Checking cache dir"); + if !state.cache_dir.exists() { + println!(" Creating cache dir"); + fs::create_dir_all(&state.cache_dir).map_err(|_| VigiError::Config)?; + } + + state.gemini_certs_path = create_file(state.cache_dir.join("gemini_certs")); + state.update_top_bar_input()?; println!("---Setup done---"); diff --git a/src-tauri/src/process_input/insecure_gemini_client.rs b/src-tauri/src/process_input/insecure_gemini_client.rs deleted file mode 100644 index 2b8e4b5..0000000 --- a/src-tauri/src/process_input/insecure_gemini_client.rs +++ /dev/null @@ -1,54 +0,0 @@ -use tokio_rustls::rustls::{ - client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}, - ClientConfig, SignatureScheme, -}; - -/// TODO: update to secure version when supported -pub fn insecure_gemini_client_config() -> ClientConfig { - ClientConfig::builder() - .dangerous() - .with_custom_certificate_verifier(std::sync::Arc::new(NoCertVerification {})) - .with_no_client_auth() -} - -#[derive(Debug)] -struct NoCertVerification; - -impl ServerCertVerifier for NoCertVerification { - fn verify_server_cert( - &self, - _end_entity: &tokio_rustls::rustls::pki_types::CertificateDer<'_>, - _intermediates: &[tokio_rustls::rustls::pki_types::CertificateDer<'_>], - _server_name: &tokio_rustls::rustls::pki_types::ServerName<'_>, - _ocsp_response: &[u8], - _now: tokio_rustls::rustls::pki_types::UnixTime, - ) -> Result { - Ok(ServerCertVerified::assertion()) - } - - fn verify_tls12_signature( - &self, - _message: &[u8], - _cert: &tokio_rustls::rustls::pki_types::CertificateDer<'_>, - _dss: &tokio_rustls::rustls::DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - - fn verify_tls13_signature( - &self, - _message: &[u8], - _cert: &tokio_rustls::rustls::pki_types::CertificateDer<'_>, - _dss: &tokio_rustls::rustls::DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - - fn supported_verify_schemes(&self) -> Vec { - vec![ - SignatureScheme::ECDSA_NISTP256_SHA256, - SignatureScheme::ECDSA_NISTP384_SHA384, - SignatureScheme::ECDSA_NISTP521_SHA512, - ] - } -} diff --git a/src-tauri/src/process_input/mod.rs b/src-tauri/src/process_input/mod.rs index a60cb07..e030fcb 100644 --- a/src-tauri/src/process_input/mod.rs +++ b/src-tauri/src/process_input/mod.rs @@ -1,9 +1,8 @@ -use crate::types::{VigiError, VigiOutput}; +use crate::types::{VigiError, VigiOutput, VigiState}; use bytes::Bytes; use mime::Mime; use url::Url; -mod insecure_gemini_client; mod process_data; mod process_url; @@ -12,11 +11,11 @@ use process_url::process_url; type ReqResult = (Mime, Bytes); -pub async fn process_input(input: &String) -> Result { +pub async fn process_input(input: &String, state: &VigiState) -> Result { let parsed = Url::parse(input); let (mime, data) = match parsed { - Ok(url) => process_url(url).await?, + Ok(url) => process_url(url, state).await?, Err(_) => Err(VigiError::Network)?, }; diff --git a/src-tauri/src/process_input/process_url.rs b/src-tauri/src/process_input/process_url.rs index e707d7d..379836f 100644 --- a/src-tauri/src/process_input/process_url.rs +++ b/src-tauri/src/process_input/process_url.rs @@ -1,15 +1,15 @@ -use crate::types::VigiError; -use insecure_gemini_client::insecure_gemini_client_config; +use crate::types::{VigiError, VigiState}; use mime::Mime; use reqwest::header::CONTENT_TYPE; +use tokio_gemini::certs::file_sscv::FileBasedCertVerifier; use url::Url; -use super::{insecure_gemini_client, ReqResult}; +use super::ReqResult; -pub async fn process_url(url: Url) -> Result { +pub async fn process_url(url: Url, state: &VigiState) -> Result { let result = match url.scheme() { "http" | "https" => process_http(url.to_string()).await?, - "gemini" => process_gemini(url.to_string()).await?, + "gemini" => process_gemini(url.to_string(), state).await?, _ => Err(VigiError::UnsupportedProtocol)?, }; @@ -37,8 +37,17 @@ async fn process_http(url: String) -> Result { )) } -async fn process_gemini(url: String) -> Result { - let mut res = tokio_gemini::Client::from(insecure_gemini_client_config()) +async fn process_gemini(url: String, state: &VigiState) -> Result { + let mut res = tokio_gemini::Client::builder() + .with_selfsigned_cert_verifier( + FileBasedCertVerifier::init(&state.gemini_certs_path.to_string_lossy().to_string()) + .await + .map_err(|e| { + println!("{:#?}", e); + VigiError::GeminiCertsFile + })?, + ) + .build() .request(&url) .await .map_err(|_| VigiError::Network)?; diff --git a/src-tauri/src/types.rs b/src-tauri/src/types.rs index 6fd59c6..fc3159b 100644 --- a/src-tauri/src/types.rs +++ b/src-tauri/src/types.rs @@ -22,6 +22,8 @@ pub enum VigiError { InvalidMimeType, InvalidCharset, + + GeminiCertsFile, } #[derive(Debug, Clone)] @@ -30,6 +32,7 @@ pub struct VigiState { pub current_tab_index_path: PathBuf, pub local_tabs_path: PathBuf, pub favorites_tabs_path: PathBuf, + pub gemini_certs_path: PathBuf, pub cache_dir: PathBuf, @@ -74,6 +77,8 @@ impl VigiState { current_tab_index_path: PathBuf::new(), local_tabs_path: PathBuf::new(), favorites_tabs_path: PathBuf::new(), + gemini_certs_path: PathBuf::new(), + cache_dir: PathBuf::new(), tabs_id_counter: 0, @@ -135,7 +140,7 @@ impl VigiState { vec![El("Type something in the address bar".into()).into()], ) } else { - process_input(&self.top_bar_input).await? + process_input(&self.top_bar_input, &self).await? } }; diff --git a/src-tauri/src/utils.rs b/src-tauri/src/utils.rs index 57898e0..46d991b 100644 --- a/src-tauri/src/utils.rs +++ b/src-tauri/src/utils.rs @@ -38,6 +38,15 @@ pub fn read_or_create_number(path: &PathBuf) -> usize { } } +pub fn create_file(path: PathBuf) -> PathBuf { + if !path.exists() { + println!(" Creating {}", path.to_string_lossy()); + File::create(&path).unwrap(); + } + + path +} + pub fn write_tabs(path: &PathBuf, tabs: &Vec) -> Result<(), VigiError> { fs::write( path,